塊級作用域綁定
之前的變量聲明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表達式為接受的每一個變量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