问题

ECMAScript 6 引入了 let 语句

我听说它被描述为“本地”变量,但我仍然不太确定它的行为与var关键字不同.

有什么区别?什么时候let应该在var上使用?

  最佳答案

范围界定规则

主要区别是范围规则.由var关键字声明的变量范围为直接函数体(因此函数范围),而let变量范围为由{ }表示的直接封闭块(因此块范围).

 function run() {
  var foo = "Foo";
  let bar = "Bar";

  console.log(foo, bar);

  {
    let baz = "Bazz";
    console.log(baz);
  }

  console.log(baz); // ReferenceError
}

run();
 

let关键字被引入语言的原因是函数范围令人困惑,是javascript中错误的主要来源之一。

看看另一个stackoverflow问题的这个例子:

 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关键字声明的变量被“存储”到块的顶部,这意味着即使在声明之前,它们也可以在其封闭范围内访问:

 function run() {
  console.log(foo); // undefined
  var foo = "Foo";
  console.log(foo); // Foo
}

run();
 

让变量在评估它们的定义之前不会初始化.在初始化之前访问它们会导致ReferenceError.变量据说从块开始直到初始化被处理为“时间死区”.

 function checkHoisting() {
  console.log(foo); // ReferenceError
  let foo = "Foo";
  console.log(foo); // Foo
}

checkHoisting();
 

创建全局对象属性

在顶层,letvar不同,不在全局对象上创建属性:

 var foo = "Foo";  // globally scoped
let bar = "Bar"; // 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, 'foo' is replaced.

let bar = "bar1";
let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared
 

  相同标签的其他问题

javascriptscopeecmascript-6varlet