區塊級作用域綁定
之前的變數宣告var無論在哪裡宣告的都被認為是作用域頂部宣告的,由於函式是一等公民,所以順序一般是function 函式名稱()、var 變數。
區塊級宣告
區塊級宣告用於宣告在指定區塊的作用域之外無法存取的變數。區塊級作用域存在於:
- 函式內部
- 區塊中(字元和
{和}之間的區域)
暫時性死區
JavaScript 引擎在掃描程式碼發現變數宣告時,要麼將它們提升至作用域頂部,要麼放到 TDZ 中。存取 TDZ 的變數會觸發執行時錯誤。只有執行過變數宣告後,變數才會從 TDZ 中移出,然後存取可正常存取。
if(condition){
console.log(typeof value) // 引用錯誤
let value = "blue";
}
// 以下的 value 並不在 TDZ 中
console.log(typeof value); // "undefined"
if(condition){
let value="blue"
}
迴圈中的區塊作用域綁定
使用let 變數只存在於 for 迴圈中,一旦迴圈結束,無法存取這個變數
for(let i=0;i<10;i++){
process(items[i]);
}
// i 在這裡不可存取,拋出一個錯誤
console.log(i);
迴圈中的函式
var宣告讓開發者在迴圈中建立函式變得異常困難,因為變數到了迴圈之外仍能存取。
var funs = [];
for(var i=0;i<10;i++){
funs.push(function(){
console.log(i)
})
}
funcs.forEach(function(func){
func(); // 輸出 10 次數字 10
})
為瞭解決這個問題,開發者們在迴圈中使用立即呼叫函式表達式(IIFE),以強制生成計數變數的副本。IIFE 表達式為接受的每一個變數 i 都建立一個副本並儲存為變數 value。這個變數的值就是相應迭代建立的函式所使用的值,因此呼叫每個函式
var funs = [];
for(var i=0;i<10;i++){
funs.push((function(value){
return function(){
console.log(i)
}
})(i))
}
funcs.forEach(function(func){
func(); // 輸出 0,1,2...
})
迴圈中的 let 宣告
let宣告模仿上述所做的一切來簡化迴圈過程,每次迭代迴圈都建立一個新變數,並以之前迭代中同名變數的值將其初始化。也適合於for-in for-of for-each
var funs = [];
for(let i=0;i<10;i++){
funs.push(function(){
console.log(i)
})
}
funcs.forEach(function(func){
func(); // 輸出 0,1,2...
})
let 宣告在迴圈內的行為是標準中專門定義的,它不一定與 let 的不提升特性相關,理解這一點至關重要。事實上,早期 let 實作中不包含這一行為。是後來加入的。
迴圈中使用 const
在for(const i=0;i<10;i++)會報錯,因為i++時試圖改變常數 i 的值。而在for-in和for-of中因為沒有去試圖改變原 i 值的操作。而是新建立了一個變數。所以執行會跟使用let宣告一樣
全域作用域綁定
let和const與var的另一個區別是它們在全域作用域中的行為。當 var 被用於全域作用域時,它會建立一個新的全域變數作為全域物件的屬性。這意味著 var 很有可能會無意中覆寫一個已經存在的全域變數。而使用let和const不能覆寫全域變數,而只能遮蔽它。so
let RegExp = 'Hello world'
console.log(window.RegExp === RegExp)
主題測試文章,只做測試使用。發佈者:Walker,轉轉請注明出處:https://walker-learn.xyz/archives/4308