先看let和var: 1. console.log(a); // undefined var a = 3; console.log(a); // Uncaught ReferenceError: Cannot access 'a' before initialization let a = 3; 在 ...
先看let和var:
1.
console.log(a); // undefined var a = 3;
console.log(a); // Uncaught ReferenceError: Cannot access 'a' before initialization let a = 3;在當前代碼執行之前,首先會把所有帶var關鍵字的進行聲明(帶function關鍵字的也會提前聲明並且定義),即所謂的變數提升,let則不存在這種情況。 ps:項目中創建函數,一般都是基於函數表達式來實現,這樣防止其提前變數提升,如:
let fn = function () {};
2.
var x = 3; console.log(window.x); // 3 let y = 3; console.log(window.y); // undefined用var進行全局變數聲明的時候,也會給全局對象(瀏覽器中即window)增加一個對應的屬性;但是用let聲明的變數不存在這個特點。 僅限於全局變數創建時有這個特點,屬於私有的執行上下文中創建的私有變數沒有這個特點。
function fn() { var x = 1; y = 2; console.log(fn.x); // undefined console.log(fn.y); // undefined } fn(); console.log(window.x); // undefined console.log(window.y); // 2
3.
var y = 21; var y = 24; console.log(y); // 24
console.log('OK'); // Uncaught SyntaxError: Identifier 'x' has already been declared let x = 21; console.log(x); let x = 24; console.log(x);可以看到,用var聲明同一個變數多次,前邊聲明的會被覆蓋以最後一次賦值為準,而用let聲明同一個變數多次時,並不是在let聲明同一變數第二次時報錯,瀏覽器顯示在代碼第一行就有報錯。 因為一段代碼在瀏覽器執行時,大體需要經過編譯階段和代碼解析階段,用var的可以重覆聲明,是因為在編譯階段中的詞法解析階段可以審核過,執行階段遇到已經聲明過的,不會再重新聲明;但是用let的不可以,是因為在詞法解析階段都過不去,所以也就不存在引擎去執行代碼的階段了。
4.
if (1 === 1) { let x = 3; console.log(x); } console.log(x); // Uncaught ReferenceError: x is not defined
let a = 1; switch (a) { case 1: let x = 2; break; } console.log(x); // Uncaught ReferenceError: x is not defined
try { let x = 100; console.log(x); // 100 console.log(a); } catch (e) { let y = 200; console.log(y); // 200 } console.log(x);// Uncaught ReferenceError: x is not defined
try { let x = 100; console.log(x); // 100 console.log(a); } catch (e) { let y = 200; console.log(y); // 200 } console.log(y); // Uncaught ReferenceError: y is not defined
從上可以看出,let存在塊級作用域,var則沒有。
再看let(var)和const
let x = 10; x = 20; console.log(x); // 20
const y = 10; y = 20; // Uncaught TypeError: Assignment to constant variable. console.log(y);
const obj = {a: 10}; obj.b = 20; console.log(obj); // {a: 10, b: 20}
let創建的變數是可以更改指針指向的,也就是可以重新賦值的,但是const聲明的變數是不允許改變指針指向的。 ps:之前有人說const創建的是常量,常量即不可更改,但從代碼示例可以看出,const聲明的基本類型值確實不允許改變,但若聲明的是存儲對象的地址指針,還是可以操作該對象的,像數字100這種才是真正的常量。