原創文章&經驗總結&從校招到A廠一路陽光一路滄桑
詳情請戳www.coderccc.com
主要知識點有:var變量提升、let聲明、const聲明、let和const的比較、塊級綁定的應用場景
1. var聲明以及變量提升
變量提升:使用var
聲明變量,變量的創建並不在聲明變量的地方,而是會在當前作用域的頂部。
如果聲明在函數內,則變量的創建則會在函數作用域的頂部;如果聲明不在函數內,則會提升到全局作用域的頂部。
示例
function getValue(condition){
if(condition){
var value = "yes";
return value;
}else{
//value 在此處可訪問,值爲 undefined
return null;
}
//value 在此處可訪問,值爲 undefined
}
等價於(var變量提升到當前函數作用域的頂部):
function getValue(condition){
var value;
if(condition){
value = "yes";
return value;
}else{
//value 在此處可訪問,值爲 undefined
return null;
}
//value 在此處可訪問,值爲 undefined
}
由變量提升會帶來循環變量過度共享的問題
2. let聲明
與var聲明變量語法一致,但是let聲明變量不會變量提升,變量的作用域只會限制在當前代碼塊中。由於let變量並不會提升到代碼塊的頂部,因此,要想讓整個代碼塊能給訪問到let變量,需要將let聲明指定到代碼塊的頂部。
示例
function getValue(condition){
if(condition){
let value = "yes";
return value;
}else{
//value 在此處不可訪問
return null;
}
//value 在此處不可訪問
}
let變量禁止重複聲明:如果一個標識符已經在代碼塊內部中被定義,那麼使用let以同樣的標識符聲明變量則會報錯
示例:
var count = 43;
let count; //重複聲明,報錯
3. const聲明
const聲明基本變量
const聲明:使用const聲明一個常量,一旦設置之後就不能再被修改,否則會報錯。也就是說,使用const聲明變量後要立即初始化。
const type;
type='TEST'; //Uncaught SyntaxError: Missing initializer in const declaration
正確的爲:
const type='TEST'
-----------------------------
const type='TEST'
type = 'DEBUG' //ObjectMethod.html:244 Uncaught TypeError: Assignment to constant variable.
const聲明對象
const只會阻止變量綁定以及變量的修改,但是不會阻止對象成員變量的修改。
const person = {name:'nancy'};
person.name= 'nike';
console.log(person.name); //nike
person = {}; //Uncaught TypeError: Assignment to constant variable.
4. let與const的比較
相同點
-
不存在變量提升:let與const聲明變量都不會存在變量提升,都只在塊級作用域內,如果試圖在代碼塊外訪問let或者const變量都會報錯;
-
禁止重複聲明:如果在同一作用域內,禁止let或者const使用以被定義的標識符聲明變量;
-
都具有暫時性死區(temporal dead zone,TDZ ):使用let或者const聲明變量,如果在聲明處之前訪問變量會報錯。在變量當前作用域的塊內,變量聲明處之前被稱之爲TDZ。
-
不會覆蓋全局對象上的屬性:let變量或者const變量會在全局作用域上創建新的變量,但是不會綁定到全局對象上(瀏覽器則是window對象),而var變量在全局作用域上會綁定到全局對象,也就是說,var全局變量可能會無意覆蓋掉全局對象上的一些屬性。
var RegExp = 'hello'; console.log(window.RegExp); //hello console.log(window.RegExp===RegExp); //RegExp覆蓋掉window對象中的RegExp屬性 ------------- let RegExp = 'hello'; console.log(window.RegExp); console.log(window.RegExp===RegExp); //false function getValue(condition){ if(condition){ //value的TDZ let value = "yes"; return value; }else{ return value; } }
不同點
- const不能再賦值,let聲明的變量可以重複賦值;
5. 塊級綁定的使用場景
-
循環內的let聲明
在循環中使用var變量,由於var變量存在變量提升,每次迭代共享同一個var變量。
for(var i = 0;i<5;i++){ setTimeout(()=>{ console.log(i); //輸出5 },1000); } console.log(i); //輸出5
解決方法:將var變量改爲let變量
//將var改成let之後 for(let i = 0; i < 5; i++) { setTimeout(() => { console.log(i) // 0,1,2,3,4 }, 0) } console.log(i)//Uncaught ReferenceError: i is not defined i無法污染外部函數
let變量不會變量提升,let變量作用域不會逃離出for循環外,因此不會污染外部函數。而在for循環中也不會每次迭代都共享同一變量,而是會分別使用let變量副本。
-
循環內const聲明
在普通的for循環中使用const變量,由於const變量不可修改,因此會報錯。而在for-in或者for-of循環中可以使用const變量。
let arr = [1,2,3,4]; for(const item of arr){ console.log(item); //輸出1,2,3,4 }
6. 總結
- let和const變量都不會進行提升,並且只會在聲明它們的代碼塊內部存在。由於變量能夠在必要位置被準確聲明,其表現更加接近其他語言;
- 塊級綁定存在暫時性死區(TDZ ) ,試圖在聲明位置之前訪問它就會導致錯誤;
- let 與 const 的表現在很多情況下都相似於 var ,然而在循環中就不是這樣。在 for-in
與 for-of 循環中, let 與 const 都能在每一次迭代時創建一個新的綁定,這意味着在循環體內創建的函數可以使用當前迭代所綁定的循環變量值(而不是像使用 var 那樣,共享同一變量值)。同時在基礎的for循環中,使用const變量會出錯。
最佳實踐:在默認情況下使用 const ,而只在你知道變量值需要被更改的情況下才使用 let 。