是否有任何理由在ES6中使用“ var”关键字?


260

Babel ES6指南说:

let是新的var

显然,唯一的区别是var将作用域限定为当前函数,而let将作用域限定为当前这个答案有一些很好的例子 。

我看不出有任何理由var在ES6代码中使用。即使您希望将给定变量的作用域限定在整个函数中,也可以let通过将声明放在功能块的顶部来实现,这是您应该执行var的操作以指示实际作用域。而且,如果您想在某个for块或某个范围内更精细地确定范围,则也可以这样做。

所以我的直觉是var在编写ES6代码时完全停止使用。

我的问题是,我对此有误吗?有什么合理的情况比它var更可取let吗?


3
我还没有尝试过(因为我还没有编写ES6代码),但是似乎var有意识地指出,此变量旨在作用于整个函数,这可能是一个有用的“自我记录”约定。
jfriend00

10
如果您let在函数的顶部放置一条语句,那么我想将其范围限定到整个函数就很明显了。我认为使用var它不会比将其定位在顶部更清晰。
卡勒姆,2015年

11
老实说,我认为唯一的原因var仍然是向后兼容。如果不是那样的话,他们将完全删除var,或者一开始就不会引入let,而是将其语义更改为var应该一直存在的含义。
约尔格W¯¯米塔格

2
@RayToal我同意Kyle Simpson所说的97%,但是他坚持使用的理由var对我来说似乎很渺茫,不足以保证会有第三种变量出现。您let只需将a放在整个函数的顶部即可将其作用于整个函数,这比var在块中写入要清晰得多(目的是将其从该块中吊起,以便可以在块外使用它) - 奇怪的)。他警告说,如果let将a 范围限定在一个函数上,那么“只是表示差异的位置,而不是语法”,但是我认为这是一件好事。
卡鲁姆,2015年

2
@RayToal我也读过该文章(在阅读本讨论之前),而我对他的弱点感到非常失望var。他提出的用于保持的示例var似乎是人为的-都是基于严重的编码错误。遇到错误并被迫修复此类错误比使用使人无法摆脱的语言功能要好得多!接下来,建议将所有内容包装在try / catch中,以防止崩溃?该链接的其余部分都很好,但是我完全不同意该部分。
Mörre

Answers:


217

道格·克罗克福德(Doug Crockford)在他的演讲“ 更好的部分let对此进行了讨论。

重点是,let避免产生误解,尤其是。对于期望通过块范围语言设定的程序员。一个var具有功能范围(它声明一个变量,在整个功能是可见的),即使它看起来像它阻止范围

var 在机器生成的代码之类的极端情况下可能仍然有用,但是我在这里努力。

const也是新的,并且具有块作用域。let x = {'hi': 'SE'}可以重新分配给之后x,而const y = x不能重新分配给之后y。这通常是可取的,因为它可以防止某些东西意外地从你身下变出来。但是要明确,y.hi = 'SO'除非你不修改对象,否则仍然可以修改对象冻结它。)

实际上,您对ES6的印象是正确的:采用letconst。停止使用var

(在“是更好的部件”的另一个表现,格说为什么===加入,而不是固定的问题====产生一些“奇怪”的结果,所以才采用===。)


一个显着的例子

Mozilla开发人员网络给出了一个示例,该示例var无法按预期运行。他们的示例是一个现实的示例,可onclick在网页中设置处理程序。这是一个较小的测试用例:

var a = [];
(function () {
   'use strict';
   for (let i = 0; i < 5; ++i) { // *** `let` works as expected ***
     a.push( function() {return i;} );
   }
} ());
console.log(a.map( function(f) {return f();} ));
// prints [0, 1, 2, 3, 4]

// Start over, but change `let` to `var`.
// prints [5, 5, 5, 5, 5]

var使我们失败的原因是,所有循环迭代都共享相同的功能范围i变量,该变量5在循环结束后具有值。


6
对于采用===而不是==,他给出了相同的答案。后者已损坏,但ES标准委员会不想更改它,因此他们添加了===不确定这意味着什么。==一点也不坏。它可以简单地定义为equality comparison using coersion退房github.com/getify/You-Dont-Know-JS/blob/master/...
AmmarCSE

13
@AmmarCSE是有关隐式强制的出色的39页文档。谁可以在编程时牢记所有这些?正如stackoverflow.com/a/359509/1682419中所概述的,道格的意思是“残破” ,简而言之,当值类型的变化超出我们的预期时,很容易得到位。你能预测所有这些吗?[ '1.0' == 1.0, [1.0] == 1.0, [1.0] == '1.0', ['1.0'] == 1.0, [null] == '', [null] == 'null', '00' == false, [] == [], [] == 0, [] == '', [] == false, [] == true, [010] - [4] == ' 4.0 ', !![0], !![1], [0] == true, [1] == true, 1 == [[1]], 0 == [[0]], '1' == [1] ]
Jerry101 '16

2
正确,大多数示例涉及数组操作数。当您研究toString及其对Objects的实现方式时,很容易理解结果。但是,如果那是坏掉的意思,那么我完全可以看出它的来历。:-)
AmmarCSE

3
为什么在不可变的时候不使用const-只是问问?我的意思是,真正的选择,它不是之间let,并var而是之间letvar以及const
shabunc

4
var按照设计工作,但没有多少人期望。这是可用性错误,而不是实现错误。
Jerry101 '17

12

如果您编写的是正确的代码,则可能无需任何语义更改就可以将所有var语句转换为let语句。

let之所以优选,是因为它会缩小标识符可见的范围。它使我们能够在首次使用的位置安全地声明变量。

const优于let。除非您需要更改引用,否则请使用const声明。这不仅具有let减少统一变量的存在,而且使代码通常更易于推理的所有优点。如果不确定是否需要突变引用,请声明它,const直到您发现自己明确需要这样做为止。


5

我不一定认为您错了,但是使用var有一些警告。从本质上讲,let应该帮助开发人员解决JavaScript的愚蠢问题,尤其是在命名冲突方面。 var似乎具有更大的作用域,因为它想转到关闭函数作用域。有时候,您需要使用var,例如您需要在函数内部的块范围内使用temp变量,否则,优先let于var将有助于开发人员解决命名冲突。简而言之,ES6即将到来let


3
var整个函数内部都提供块中的临时温度,而不是块范围内的。这是一个误导性功能。
Jerry101'2015-2-24

1

我倾向于同意在es6中仅应使用“ let”。AFIK,重新声明“ let”会产生错误(很好),而使用“ var”时,您只需覆盖该值(尽管es5中的“严格模式”也可以解决此问题)。


-4

let表示“让变量相等”。这是一个声明,换句话说,是一个初始化和赋值。

它与const“常数”的含义相反,后者与变量相反。

其他一些语言在声明时使用实际对象的前缀而不是对象(例如,这def是“定义函数”的简写-完全缺少“定义”的含义)。

Let 将这种语义上的不一致添加到Javascript中。

从逻辑上讲,您也可以让常量等于某个值,因为“ let”关键字的工作是分配内存。

出现问题是因为var关键字是在const支持之前引入的,因此向后兼容性表明var不必表示变量。(它也可以用来分配一个常数。)

因此,引入let位置错误。为了确保我们从词法上记住这是错误的,他们还决定更改letvs 的词法范围var,因此在调试时我们首先想到的是不一致。

换句话说,let之所以存在是因为人们(意味着语言维护者)认为Javascript过于一致,在掌握了所有习语和特质之后就渴望更多。

附带说明,var如果要将“块”视为闭包,则在“箭头”块中不起作用(因为var是在将块视为闭包之前引入的)let


6
-1:学究,无助且主要基于意见。
乔尔·穆勒

fijiaaron在这里只是和我们开玩笑。
Jerry101 '16

我很同情您不喜欢词汇形式,let因为它与JavaScript中同一类别中其他关键字的语气不一致。但这仍然不能回答问题,并且放置得也不是很好。投票
Aluan Haddad

3
let不仅仅是开发人员想要更多的复杂性。实际上,从直观上更容易理解,因为当您对vars进行循环和关闭时,闭包将保留var的最后一个值,但是当您对let进行相同的操作时,循环中的每个闭包对于let来说都有自己的值,上面@ Jerry101的示例
TKoL
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.