在JavaScript中,let
、const
?和?var
?是用來聲明變量的關鍵字,但它們之間在作用域、變量提升、重復聲明等方面存在區別,詳細情況如下:
1.?let
、const
、var
?的區別
(1) 塊級作用域
-
let
?和?const
:具有塊級作用域,由?{}
?包括。這解決了ES5中內層變量可能覆蓋外層變量和循環變量泄露為全局變量的問題。
if(true){let a="hello world";console.log(a);//hello world
}
//console.log(a);//報錯,ReferenceError: a is not defined//因為let、const在塊外部不可見
-
var
:不具備塊級作用域,只有函數作用域或全局作用域。
if(true){var b="hello world";console.log(b);//hello world
}
console.log(b);//hello world//因為var聲明的變量在函數作用域或全局作用域內有效
(2) 變量提升(var特有)
var
:存在變量提升,即變量可以在聲明之前使用,但值為?undefined
。
console.log(x); // undefined
var x = 10;//因為var聲明的變量會被提升
let
?和?const
:不存在變量提升,必須在聲明后才能使用,否則報錯。
console.log(y); // 報錯,ReferenceError: Cannot access 'y' before initialization
let y = 10;//因為let、const聲明的變量不會被提升
(3) 全局屬性
var
:聲明的全局變量會成為全局對象(瀏覽器中是?window
,Node中是?global
)的屬性。let
?和?const
:不會將聲明的全局變量添加到全局對象的屬性上。
(4) 重復聲明
var
:允許在同一作用域內重復聲明變量,后聲明的會覆蓋前面聲明的。
var c = 1;
var c = 2;
console.log(c); // 2
let
?和?const
:不允許在同一作用域內重復聲明變量。
let d = 1;
let d = 2; // 報錯,SyntaxError: Identifier 'd' has already been declaredconst e = 1;
// const e = 2; // 報錯//因為let、const不允許在同一作用域內重復聲明變量
(5) 暫時性死區(let、const特有)
let
?和?const
:在聲明前使用會報錯,因為這段時間稱為暫時性死區。
if (true) { console.log(f); // 報錯,因為f在聲明之前處于暫時性死區 let f = 'temporal dead zone';
} // const的情況與let相同,也會存在暫時性死區
var
:不存在暫時性死區。
(6) 初始值設置
var
?和?let
:可以不設置初始值。
var g; // 未初始化
console.log(g); // undefined let h; // 未初始化,但在使用前必須聲明
console.log(h); // undefined
const
:必須設置初始值。
// const i; // 報錯,因為const必須設置初始值
const j = 10;
console.log(j); // 輸出 10
(7) 指針指向
let、var
:創建的變量可以重新賦值,即可以更改指針指向。const
:聲明的變量不允許改變指針的指向,但如果是對象或數組,可以修改其內部屬性或元素。
2.?const
?對象的屬性可以修改
const
?保證的是變量指向的內存地址不變,即不能重新指向另一個對象或數組。
但對于對象或數組這樣的引用類型,const
?只能確保引用(指針)不變,而不能保證對象內部狀態的不可變性。
因此,可以修改?const
?聲明的對象的屬性或數組的元素。
const obj = { value: 10 };
obj.value = 20; // 可以修改const聲明對象的屬性
console.log(obj.value); // 20 // obj = { value: 30 }; // 報錯,因為嘗試改變了const聲明的對象的引用
3.其他說明
(1)變量提升是var
特有的,且只影響函數作用域或全局作用域;而暫時性死區是let
和const
特有的,與它們的塊級作用域緊密相關。
(2)const
用于聲明一個只讀的常量。一旦一個常量被賦值后,它的值就不能再被改變。但是,如果常量是一個對象或數組,其內部狀態仍然可以被修改,只是常量指向的內存地址不能改變。使用const
可以提高代碼的可讀性和可維護性,因為它明確表示了某些值是不應該被改變的。
(3)使用var
在全局作用域中聲明的變量會自動成為全局對象(在瀏覽器中是window
,在Node.js中是global
)的屬性。這可能會導致意外的全局變量污染和命名沖突。所以使用let
和const
在全局作用域中聲明的變量則不會成為全局對象的屬性,這有助于減少全局命名空間的污染。
(4)由于let
和const
提供了更好的封裝和避免命名沖突的能力,它們通常被認為是更好的選擇。
總結
區別 | let | const | var |
---|---|---|---|
有無塊級作用域 | √ | √ | × |
有無變量提升 | × | × | √ |
能否添加全局屬性 | × | × | √ |
能否重復聲明變量 | × | × | √ |
有無暫時性死區 | √ | √ | × |
必須設置初始值 | × | √ | × |
能否改變指針指向 | √ | × | √ |