var提高以下:es6
function getValue(condition) { if (condition) { var value = "blue"; // 其餘代碼 return value; } else { // value 在此處可訪問,值爲 undefined return null; } // value 在此處可訪問,值爲 undefined }
以下所示:瀏覽器
function getValue(condition) { if (condition) { let value = "blue"; // 其餘代碼 return value; } else { // value 在此處不可用 return null; } // value 在此處不可用 }
若是一個標識符已經在代碼內部被定義,重複進行let聲明會報錯安全
var a = 30; //報錯 let a = 30;
var count = 30; // 不會拋出錯誤 if (condition) { let count = 40; // 其餘代碼 }
// 有效的常量 const maxItems = 30; // 語法錯誤:未進行初始化 const name;
const person = { name: "Nicholas" }; // 工做正常 person.name = "Greg"; // 拋出錯誤 person = { name: "Greg" };
if (condition) { const maxItems = 5; // 其餘代碼 } // maxItems 在此處沒法訪問
for (var i = 0; i < 10; i++) { process(items[i]); } // i 在此處仍然可被訪問 console.log(i); // 10
輸出的結果並非預期的值而是10;是由於var聲明致使的變量的提高。聰明的你確定會想到使用塊級綁定來進行變量聲明併發
for (let i = 0; i < 10; i++) { process(items[i]); } console.log(i);
i在此處是否是會正常輸出呢,其實不會,在這個例子中會致使報錯,爲何呢?由於i在此處不可訪問。本例中的變量 i 僅在 for 循環內部可用,一旦循環結束,該變量在任意位置都不可訪問。函數
咱們在來看看一下代碼code
var funcs = []; for (var i = 0; i < 10; i++) { funcs.push(function() { console.log(i); }); } funcs.forEach(function(func) { func(); // 輸出數值 "10" 十次 });
你本來可能預期這段代碼會輸出 0 到 9 的數值,但它卻在同一行將數值 10 輸出了十次。這是
由於變量 i 在循環的每次迭代中都被共享了,意味着循環內建立的那些函數都擁有對於同一
變量的引用。在循環結束後,變量 i 的值會是 10 ,所以當 console.log(i) 被調用時,
每次都打印出 10 。對象
爲了修正這個問題,開發者在循環內使用當即調用函數表達式(IIFEs),以便在每次迭代中
強制建立變量的一個新副本,示例以下:作用域
var funcs = []; for (var i = 0; i < 10; i++) { funcs.push((function(value) { return function() { console.log(value); } }(i))); } funcs.forEach(function(func) { func(); // 從 0 到 9 依次輸出 });
let 聲明經過有效模仿上例中 IIFE 的做用而簡化了循環。在每次迭代中,都會建立一個新的
同名變量並對其進行初始化。這意味着你能夠徹底省略 IIFE 而得到預期的結果,就像這樣開發
var funcs = []; for (let i = 0; i < 10; i++) { funcs.push(function() { console.log(i); }); } funcs.forEach(function(func) { func(); // 從 0 到 9 依次輸出 })
咱們是否會想到這個問題:爲何一樣的代碼使用let聲明會致使不同的結果呢?
在循環中let聲明每次都建立了一個新的i變量,所以在循環內部建立的函數得到了各自的i副本,而每一個i副本的值都會在每次的循環迭代聲明變量的時候肯定了get
var funcs = [], object = { a: true, b: true, c: true }; for (let key in object) { funcs.push(function() { console.log(key); }); } funcs.forEach(function(func) { func(); // 依次輸出 "a"、 "b"、 "c" });
本例中的 for-in 循環體現出了與 for 循環相同的行爲。每次循環,一個新的 key 變量綁
定就被建立,所以每一個函數都可以擁有它自身的 key 變量副本,結果每一個函數都輸出了一個
不一樣的值。而若是使用 var 來聲明 key ,則全部函數都只會輸出 "c" 。
let 聲明在循環內部的行爲是在規範中特別定義的,而與不提高變
量聲明的特徵沒有必然聯繫。事實上,在早期 let 的實現中並無這種行爲,它是後來
才添加的。
雖然es6沒有明確的規範咱們不能在for循環中使用const聲明,然而它會根據循環方式的不一樣而有不一樣的行爲,咱們能夠在初始化時使用const,可是當循環試圖改變變量的值的時候會拋出錯誤,例如:
var funcs = []; // 在一次迭代後拋出錯誤 for (const i = 0; i < 10; i++) { funcs.push(function() { console.log(i); }); }
在此代碼中, i 被聲明爲一個常量。循環的第一次迭代成功執行,此時 i 的值爲 0 。在
i++ 執行時,一個錯誤會被拋出,由於該語句試圖更改常量的值。所以,在循環中你只能使
用 const 來聲明一個不會被更改的變量
而另外一方面, const 變量在 for-in 或 for-of 循環中使用時,與 let 變量效果相同。因
此下面代碼不會致使出錯:
var funcs = [], object = { a: true, b: true, c: true }; // 不會致使錯誤 for (const key in object) { funcs.push(function() { console.log(key); }); } funcs.forEach(function(func) { func(); // 依次輸出 "a"、 "b"、 "c" });
這段代碼與「循環內的 let 聲明」小節的第二個例子幾乎徹底同樣,惟一的區別是 key 的值在
循環內不能被更改。 const 可以在 for-in 與 for-of 循環內工做,是由於循環爲每次迭
代建立了一個新的變量綁定,而不是試圖去修改已綁定的變量的值(就像使用了 for 而不是
for-in 的上個例子那樣)。
let 與 const 不一樣於 var 的另外一個方面是在全局做用域上的表現。當在全局做用域上使 用 var 時,它會建立一個新的全局變量,併成爲全局對象(在瀏覽器中是 window )的一 個屬性。