ECMAScript 6 introduced the let
statement.
我听说它被描述为一个local
变量,但我仍然不确定它的行为与var
关键字有什么不同.
有什么不同?什么时候应该用let
而不是var
?
let
statement.我听说它被描述为一个local
变量,但我仍然不确定它的行为与var
关键字有什么不同.
有什么不同?什么时候应该用let
而不是var
?
主要区别在于作用域规则.由var
关键字声明的变量的作用域为直接函数体(因此为函数作用域),而let
个变量的作用域为由{ }
表示的即时enclosing挡路(因此为挡路作用域).
function run() {
var foo = "Foo";
let bar = "Bar";
console.log(foo, bar); // Foo Bar
{
var moo = "Mooo"
let baz = "Bazz";
console.log(moo, baz); // Mooo Bazz
}
console.log(moo); // Mooo
console.log(baz); // ReferenceError
}
run();
在语言中引入let
关键字的原因是函数范围令人困惑,并且是JavaScript中错误的主要来源之一.
让我们来看看这个来自another Stack Overflow question的例子:
var funcs = [];
// let's create 3 functions
for (var i = 0; i < 3; i++) {
// and store them in funcs
funcs[i] = function() {
// each should log its value.
console.log("My value: " + i);
};
}
for (var j = 0; j < 3; j++) {
// and now let's run each one to see
funcs[j]();
}
由于匿名函数绑定到同一个变量,所以每次调用funcs[j]();
时,都会将My value: 3
输出到控制台.
人们必须创建立即调用的函数来从循环中捕获正确的值,但这也很麻烦.
而用var
关键字声明的变量是hoisted(在代码运行之前用undefined
初始化),这意味着即使在声明它们之前,也可以在它们的封闭作用域中访问它们:
function run() {
console.log(foo); // undefined
var foo = "Foo";
console.log(foo); // Foo
}
run();
let
个变量在其定义被判断之前不会初始化.在初始化之前访问它们会导致错误.从块的开始到初始化被处理,变量被称为处于"时间死区".
function checkHoisting() {
console.log(foo); // ReferenceError
let foo = "Foo";
console.log(foo); // Foo
}
checkHoisting();
在顶层,与var
不同,let
不会在全局对象上创建属性:
var foo = "Foo"; // globally scoped
let bar = "Bar"; // not allowed to be globally scoped
console.log(window.foo); // Foo
console.log(window.bar); // undefined
在严格模式下,var
将允许您在同一范围内重新声明同一变量,而let
将引发SyntaxError.
'use strict';
var foo = "foo1";
var foo = "foo2"; // No problem, 'foo1' is replaced with 'foo2'.
let bar = "bar1";
let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared