您好,登錄后才能下訂單哦!
這篇文章主要介紹“JavaScript中的變量提升實例分析”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“JavaScript中的變量提升實例分析”文章能幫助大家解決問題。
JavaScript中奇怪的一點是你可以在變量和函數聲明之前使用它們。就好像是變量聲明和函數聲明被提升了代碼的頂部一樣。
sayHi() // Hi there! function sayHi() { console.log('Hi there!') } name = 'John Doe' console.log(name) // John Doe var name
然而JavaScript并不會移動你的代碼,所以JavaScript中“變量提升”并不是真正意義上的“提升”。
JavaScript是單線程語言,所以執行肯定是按順序執行。但是并不是逐行的分析和執行,而是一段一段地分析執行,會先進行編譯階段然后才是執行階段。
在編譯階段階段,代碼真正執行前的幾毫秒,會檢測到所有的變量和函數聲明,所有這些函數和變量聲明都被添加到名為Lexical Environmen
t的JavaScript數據結構內的內存中。所以這些變量和函數能在它們真正被聲明之前使用。
sayHi() // Hi there! function sayHi() { console.log('Hi there!') }
因為函數聲明在編譯階段會被添加到詞法環境(Lexical Environment)中,當JavaScript引擎遇到sayHi()
函數時,它會從詞法環境中找到這個函數并執行它。
lexicalEnvironment = { sayHi: < func > }
console.log(name) // 'undefined' var name = 'John Doe' console.log(name) // John Doe
上面的代碼實際上分為兩個部分:
var name
表示聲明變量name
= 'John Doe'
表示的是為變量name
賦值為'John Doe'。
var name // 聲明變量 name = 'John Doe' // 賦值操作
只有聲明操作var name
會被提升,而賦值這個操作并不會被提升,但是為什么變量name
的值會是undefined
呢?
原因是當JavaScript在編譯階段會找到var
關鍵字聲明的變量會添加到詞法環境中,并初始化一個值undefined
,在之后執行代碼到賦值語句時,會把值賦值到這個變量。
// 編譯階段 lexicalEnvironment = { name: undefined } // 執行階段 lexicalEnvironment = { name: 'John Doe' }
所以函數表達式也不會被“提升”。helloWorld
是一個默認值是undefined
的變量,而不是一個function
。
helloWorld(); // TypeError: helloWorld is not a function var helloWorld = function(){ console.log('Hello World!'); }
console.log(a) // ReferenceError: a is not defined let a = 3
為什么會報一個ReferenceError
錯誤,難道let
和const
聲明的變量沒有被“提升”嗎?
事實上所有的聲明(function, var, let, const, class)都會被“提升”。但是只有使用var
關鍵字聲明的變量才會被初始化undefined
值,而let
和const
聲明的變量則不會被初始化值。
只有在執行階段JavaScript引擎在遇到他們的詞法綁定(賦值)時,他們才會被初始化。這意味著在JavaScript引擎在聲明變量之前,無法訪問該變量。這就是我們所說的Temporal Dead Zone,即變量創建和初始化之間的時間跨度,它們無法訪問。
如果JavaScript引擎在let
和const
變量被聲明的地方還找不到值的話,就會被賦值為undefined
或者返回一個錯誤(const
的情況下)。
舉例:
let a console.log(a) // undefined a = 5
在編譯階段,JavaScript引擎遇到變量a
并將它存到詞法環境中,但因為使用let
關鍵字聲明的,JavaScript引擎并不會為它初始化值,所以在編譯階段,此刻的詞法環境像這樣:
lexicalEnvironment = { a: <uninitialized> }
如果我們要在變量聲明之前使用變量,JavaScript引擎會從詞法環境中獲取變量的值,但是變量此時還是uninitialized
狀態,所以會返回一個錯誤ReferenceError
。
在執行階段,當JavaScript引擎執行到變量被聲明的時候,如果聲明了變量并賦值,會更新詞法環境中的值,如果只是聲明了變量沒有被賦值,那么JavaScript引擎會給變量賦值為undefined
。
tips: 我們可以在let
和const
聲明之前使用他們,只要代碼不是在變量聲明之前執行:
function foo() { console.log(name) } let name = 'John Doe' foo() // 'John Doe'
同let
和const
一樣,class
在JavaScript中也是會被“提升”的,在被真正賦值之前都不會被初始化值, 同樣受Temporal Dead Zone的影響。
let peter = new Person('Peter', 25) // ReferenceError: Person is not defined class Person { constructor(name, age) { this.name = name; this.age = age; } } let John = new Person('John', 25); console.log(John) // Person { name: 'John', age: 25 }
關于“JavaScript中的變量提升實例分析”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。