为什么var没有被弃用?

21

最近ES6发布后,许多资源建议我在JavaScript中使用"const"和"let"代替"var",并且应该停止使用"var"。

我想知道的是,如果在所有方面上"var"没有优势,为什么他们不只是修复"var"甚至将其弃用,而不是让它们并存呢?


9
因为更改或删除它将导致约十亿行代码出错。 - user8897421
5
当您需要函数作用域而不是块级作用域时,varlet 更有用。 - Paul
1
var 仍然有其用途。 - jhpratt
2
那么您的用例是在块内声明一个变量,然后在块外使用它? - user8897421
3
在任何好公司的代码审查中,这都无法通过审核......而且肯定会被任何代码检查工具否决。 - Shadow
显示剩余9条评论
3个回答

29

向后兼容性。

如果您在函数开头定义它们,使用varlet没有实质性的优势,它们的含义基本相同。

您说得对,除非涉及到this,否则没有真正的理由写新代码时使用var

然而,互联网上有些页面已经存在几十年了,没有人会重写它们。从语言中删除var并没有什么实际收益。对于像HTML和JavaScript这样的解释性语言,向后兼容性是绝对必要的。

这也是为什么他们选择不简单地重新定义var的原因。以下是一个示例代码:

// THIS IS AN EXAMPLE OF BAD CODE. DO NOT COPY AND PASTE THIS.
if (logic) {
    var output = "true"
} else {
    var output = "false"
}
console.log(output)

如果将var更改为像let那样运作,那么由于作用域的差异,console.log会导致引用错误。

谢谢你的回答,我很感激。 然而,你的回答只解决了一个问题,即“为什么不废弃var”。 从一开始重构“var”,而不引入任何“let”呢?这样做有好的理由吗? - Leonard Li
1
再次强调向后兼容性。如果人们按照您问题中评论所描述的可怕方式使用var(这确实会发生),那么该代码的含义将发生变化并且可能会崩溃,对于编写它的开发人员来说可能没有任何警告。 - Shadow
我已经添加了一个例子。 - Shadow
我总是认为你展示的例子形式不好。最好在更高的范围声明变量。这意味着我不认为这是var的一个好用法的好例子。 - jfriend00
3
我同意 - 也许我应该更明显地表达这一点。然而,这是一个很好的例子,说明仅仅将 var 改成 let 是一个不好的想法,这也是本意所在。 - Shadow
向后兼容性是编程世界中所有烂摊子的根源。 - Robo Robok

1
我认为有时需要重新声明变量以减少代码量。
一个例子是生成唯一ID的函数:
function makeUniqueId(takenIds) {
  do {
    var id = Number.parseInt(Math.random() * 10);
  } while (takenIds.includes(id))
}

这可以这样调用:
makeUniqueId([1,2,3,4,5,6,7])

在这里,我在do块内简单地声明了id变量,并将其“提升”到函数范围。如果我使用let,那么会导致错误,因为while块将无法看到来自do块的变量。当然,我可以在do..while之前声明let,但这会创建具有额外代码行的相同函数作用域变量。 另一个例子是当您将代码复制粘贴到devtools控制台中时,每次变量都会被重新声明。 再来一个例子。如果您想将变量声明保持靠近其用法,但仍将它们视为函数全局变量,该怎么办?如果以这种方式使用let,则在dev工具中会得到相当令人困惑的体验(所有这些Block、Block scopes)。 enter image description here 但是var将它们保持在一个“本地”列表中: 在此输入图片描述

3
正如您所看到的,id 变量可能会被重新声明多次...但实际上不会。当控制进入新的执行环境(或块作用域声明)时,声明语句只会处理一次。在执行 makeUniqueId 函数体的任何部分之前,id 变量已经具有函数范围。这里没有 while 块,只有 while 表达式。您是对的,在 do..while 循环中使用 let 声明的变量作用域不会延伸到 while 条件语句,所以如果在 do 块中使用 let 声明,则 id 变量将超出其作用域。 - RobG
谢谢你发现了这个问题! - vloginov
所有这些用例都不足以保留 var。它带来的混乱和错误比好处更多。简化将不胜感激。 - Joan
所有的例子都恰恰相反:[ex. 1]:id 的逻辑应该在外部范围内,必须在那里声明,而不是在 _do{} _中,然后使用let; [ex. 2]:复制粘贴重新声明变量非常危险;使用let将明确显示问题;[ex. 3]与1类似:您说您想要在其使用附近声明一个变量,但您希望将其视为全局变量:因此声明必须在全局范围内。一般来说,除非在模块模式(即const声明的对象)中,否则不明智使用全局变量。 - allez l'OM

-1

每种变量声明方式都有其优缺点,使用var、const和let取决于它们的用例。

var

变量声明在代码执行之前进行处理。 使用 var 声明的 JavaScript 变量的作用域是其当前执行上下文。 在函数外部声明的 JavaScript 变量的作用域是全局的。

let

let语句允许您创建一个变量,其作用域仅限于使用它的块。

const

const语句的值只能被赋值一次,且不能重新赋值。const语句的作用域与let语句类似。

希望你理解。


2
你没有列出使用 var 的任何优点。你也可以在函数或全局级别使用 let,那么除了在块中声明一个 var 但在该块之外使用它这样的不愉快行为之外,还有什么优势呢? - user8897421
1
“变量声明在代码执行之前被处理” - 对于 letconst 也是如此。 - Bergi
1
请注意,“变量声明”包括letconst(根据ECMA-262 §13.3.1),它们在代码执行之前都会被处理(但是赋值是在代码执行时进行的)。;-) - RobG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接