學習JavaScript範圍的基礎知識

範圍是一組定義在編程語言中以確定變量值的規則。

JavaScript使用詞法範圍,這意味著變量的值由其在被寫入時的位置所定義,而不是在其被調用時,這是與另一種替代方式動態範圍不同的事情。

範圍是對程序的部分可見的變量集合。

我們有全局範圍,區塊範圍和函數範圍。如果一個變量在函數或區塊外部定義,它將附加到全局對象並具有全局範圍,這意味著它在程序的每個部分都可用。

varletconst聲明之間有一個非常重要的區別。

在函數內部定義為var的變量只在該函數內部可見,就像函數參數一樣。

另一方面,在其所在的塊內定義為constlet的變量只在該塊內部可見。

重要的是要理解,塊(由一對花括號標識)不為var定義新的範圍,但對於letconst則有。只有在創建函數時,才為var創建新的範圍,因為var沒有塊範圍,而是函數範圍。

在函數內部,任何在其中定義的var變量在所有函數代碼中都可見,即使該變量在函數結束時聲明,它仍然可以在開頭引用,因為JavaScript在執行代碼之前實際上會將所有變量聲明移動到頂部(這被稱為提升)。為避免混淆,始終在函數開頭聲明var變量。

這就是我的意思。即使你在函數結尾聲明了一個var變量,它的聲明也會被移到頂部:

function run() {
 console.log(`${name}`)
 var name = 'Flavio'
}

run()

這將打印出“undefined”,因為實際上發生的是:

function run() {
 var name;
 console.log(`${name}`)
 name = 'Flavio'
}

run()

letconst不會“受到”提升的影響。如果在上面的示例中使用它們之一,則會出現錯誤:ReferenceError: name is not defined

在JavaScript中,父函數的變量也可以在內部函數中使用。內部函數的範圍還包括父函數的範圍,這稱為閉包(我們將在後面更詳細地談論這一點)。

你需要注意一點。在非嚴格模式下,如果你使用未聲明的變量,無論你在哪裡使用,該變量都會附加到全局範圍。這可能是錯誤的根源。所以,在使用變量之前,請確保始終聲明變量。只是要意識到這一點,但這只是預設情況下使用嚴格模式的另一個原因,嚴格模式可以解決這個問題。我們之後再談論嚴格模式。

記住:在具有與全局變量同名的函數(或塊)中定義的任何變量優先於全局變量,遮蔽它。

這將打印undefined

var name = 'Roger'

function run() {
 console.log(`${name}`)
 var name = 'Flavio'
}

run()

而這將引發錯誤ReferenceError: name is not defined

let name = 'Roger'

function run() {
 console.log(`${name}`)
 let name = 'Flavio'
}

run()