問題

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