[ES6深度解析]13:let const (2)

let和var是不同的,所以如果你只是做一个全球搜索替换整个代码,可以破坏部分的代码(可能是无意中)。但在大多数情况下,在新ES6代码,你应该停止使用var,并在之前使用var的位置使用let。因此有这样的口号:“let是新的var”。

let和var之间到底有什么区别?

let变量是块作用域的。
用let声明的变量的作用域只是封闭的块,而不是整个封闭的函数。使用let还是会有变量提升,但不是不分青红皂白。runTowerExperiment示例可以通过简单地将var更改为let来修复。如果你在任何地方都使用let,你就不会有那种bug了。

全局let变量不是全局对象的属性
也就是说,您不会通过写入window.variableName来访问它们。相反,它们存在于一个无形的块的范围内,该块理论上包含了在网页中运行的所有JS代码。

for (let x…)形式的循环在每次迭代中为x创建一个新的绑定。
这是一个非常微妙的差别。这意味着,如果for (let…)循环执行多次,并且该循环包含一个闭包,就像在我们正在讨论的console.log示例中那样,每个闭包将捕获循环变量的不同副本,而不是所有闭包捕获相同的循环变量。所以上面那个例子可以用let替换var就可以解决错误:

var messages = ["Meow!", "I'm a talking cat!", "Callbacks are fun!"]; for (let i = 0; i < messages.length; i++) { setTimeout(function () { console.log(messages[i]); }, i * 1500); }

这适用于所有三种for循环:for-of、for-in和带有分号的老式C类型循环。

在到达let变量声明之前尝试使用它是错误的。
在控制流到达声明变量的代码行之前,变量是未初始化的。例如:

function update() { console.log("current time:", t); // ReferenceError ... let t = readTachymeter(); }

这条规则是用来帮助你捕捉bug的。你将在问题所在的代码行上得到一个异常,而不是NaN。

当变量在作用域内但未初始化时,这个时间段称为临时死区(temporal dead zone)。我一直在期待这句有灵感的行话能一跃成为科幻小说。还没有。

一个琐碎的性能细节:在大多数情况下,你可以通过查看代码来判断声明是否已经运行,因此JavaScript引擎实际上不需要在每次访问变量时执行额外的检查,以确保它已初始化。然而,在一个封闭的内部,有时是不清楚的。在这些情况下,JavaScript引擎将执行运行时检查。这意味着let比var要慢。

一个复杂的交替域作用域细节:在一些编程语言中,变量的作用域从声明点开始,而不是向后覆盖整个封闭块。标准委员会考虑对let使用这种范围规则。这样的话,t的使用导致这里的ReferenceError不会在后面的let t的范围内,所以它根本不会引用那个变量。它可以指封闭作用域中的t。但这种方法不适用于闭包或函数提升,因此最终被放弃。

用let重新声明变量是一个SyntaxError错误。
这条规则也可以帮助你发现微小的错误。不过,如果你尝试全局的let-to-var转换,这种差异很可能会给你带来一些问题,因为它甚至适用于全局的let变量。

如果你有几个脚本都声明了相同的全局变量,你最好继续使用var。如果切换到let,那么无论第二次加载哪个脚本都会失败并出现错误。

或者使用ES6模块。

一个的语法细节:let是严格模式代码中的保留字。在非严格模式的代码中,为了向后兼容,你仍然可以声明变量、函数和名为let的参数——你可以写var let = 'q'! let let = 1这是不允许的。

除了这些区别之外,let和var几乎是相同的。例如,它们都支持声明用逗号分隔的多个变量,并且都支持解构。注意,类声明的行为类似于let,而不是var。如果你多次加载一个包含类的脚本,第二次重新声明类时就会得到一个错误。

const

ES6还引入了第三个可与let一起使用的关键字:const。

用const声明的变量就像let一样,你只能在它们被声明的地方赋值。否则是一个SyntaxError。

const MAX_CAT_SIZE_KG = 3000; //

分类:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyxpws.html