ECMAScript 6 引入了let
语句 。我听说它被描述为 “本地” 变量,但我仍然不太确定它与var
关键字的行为方式有何不同。
有什么区别?什么时候应该let
在使用var
?
区别在于范围界定。 var
的作用范围是最接近的功能块和let
可以被限制在最近的封闭块,其可以是比功能块小。如果在任何区域之外,两者都是全球
此外,使用let
声明的变量在它们的封闭块中声明之前是不可访问的。如演示中所示,这将引发 ReferenceError 异常。
演示 :
var html = '';
write('#### global ####\n');
write('globalVar: ' + globalVar); //undefined, but visible
try {
write('globalLet: ' + globalLet); //undefined, *not* visible
} catch (exception) {
write('globalLet: exception');
}
write('\nset variables');
var globalVar = 'globalVar';
let globalLet = 'globalLet';
write('\nglobalVar: ' + globalVar);
write('globalLet: ' + globalLet);
function functionScoped() {
write('\n#### function ####');
write('\nfunctionVar: ' + functionVar); //undefined, but visible
try {
write('functionLet: ' + functionLet); //undefined, *not* visible
} catch (exception) {
write('functionLet: exception');
}
write('\nset variables');
var functionVar = 'functionVar';
let functionLet = 'functionLet';
write('\nfunctionVar: ' + functionVar);
write('functionLet: ' + functionLet);
}
function blockScoped() {
write('\n#### block ####');
write('\nblockVar: ' + blockVar); //undefined, but visible
try {
write('blockLet: ' + blockLet); //undefined, *not* visible
} catch (exception) {
write('blockLet: exception');
}
for (var blockVar = 'blockVar', blockIndex = 0; blockIndex < 1; blockIndex++) {
write('\nblockVar: ' + blockVar); // visible here and whole function
};
for (let blockLet = 'blockLet', letIndex = 0; letIndex < 1; letIndex++) {
write('blockLet: ' + blockLet); // visible only here
};
write('\nblockVar: ' + blockVar);
try {
write('blockLet: ' + blockLet); //undefined, *not* visible
} catch (exception) {
write('blockLet: exception');
}
}
function write(line) {
html += (line ? line : '') + '<br />';
}
functionScoped();
blockScoped();
document.getElementById('results').innerHTML = html;
<pre id="results"></pre>
在功能块之外使用它们非常相似。
let me = 'go'; // globally scoped
var i = 'able'; // globally scoped
但是,使用let
定义的全局变量不会作为属性添加到全局window
对象上,就像使用var
定义的那样。
console.log(window.me); // undefined
console.log(window.i); // 'able'
在功能块中使用时它们是相同的。
function ingWithinEstablishedParameters() {
let terOfRecommendation = 'awesome worker!'; //function block scoped
var sityCheerleading = 'go!'; //function block scoped
}
这是区别。 let
仅在for()
循环中可见, var
对整个函数可见。
function allyIlliterate() {
//tuce is *not* visible out here
for( let tuce = 0; tuce < 5; tuce++ ) {
//tuce is only visible in here (and in the for() parentheses)
//and there is a separate tuce variable for each iteration of the loop
}
//tuce is *not* visible out here
}
function byE40() {
//nish *is* visible out here
for( var nish = 0; nish < 5; nish++ ) {
//nish is visible to the whole function
}
//nish *is* visible out here
}
假设严格模式, var
将允许您在同一范围内重新声明相同的变量。另一方面, let
不会:
'use strict';
let me = 'foo';
let me = 'bar'; // SyntaxError: Identifier 'me' has already been declared
'use strict';
var me = 'foo';
var me = 'bar'; // No problem, `me` is replaced.
let
也可以用来避免闭包问题。它绑定了新的价值,而不是保留旧的参考,如下面的例子所示。
for(var i = 1; i < 6; i++) {
document.getElementById('my-element' + i)
.addEventListener('click', function() { alert(i) })
}
上面的代码演示了一个典型的 JavaScript 闭包问题对i
变量的引用存储在单击处理程序闭包中,而不是i
的实际值。
每个单击处理程序都将引用同一个对象,因为只有一个计数器对象可以容纳 6,因此每次单击时会得到 6 个。
一般的解决方法是将它包装在一个匿名函数中并将i
作为参数传递。现在也可以通过使用let
代替var
来避免这些问题,如下面的代码所示。
演示 (在 Chrome 和 Firefox 50 中测试)
'use strict';
for(let i = 1; i < 6; i++) {
document.getElementById('my-element' + i)
.addEventListener('click', function() { alert(i) })
}