您好,登錄后才能下訂單哦!
了解javascript聲明提升是什么?這個問題可能是我們日常學習或工作經常見到的。希望通過這個問題能讓你收獲頗深。下面是小編給大家帶來的參考內容,讓我們一起來看看吧!
Javascript聲明提升
在分析聲明提升之前,我認為有必要知道的兩點:
一、引擎查詢變量的兩種方式
引擎查詢變量的方式可以分為LHS和RHS兩種方式,通過“L”和“R”是可以大致了解意思,分別是賦值操作的左側和右側。 (不能光是理解為“=”的左右側可不行,因為賦值操作的形式有多種。)
簡單說下我對這兩種查詢方式的理解:
LHS:賦值操作的目標是誰。 (查詢變量)
RHS:誰是賦值操作的源頭。 (查詢變量的值)
這樣說可能有些難以理解,舉個栗子:
function foo(a){ //這里存在一個隱式變量分配,LHS查詢變量a,并賦值2. //隱式a = 2; //左邊LHS查詢變量b,查詢作用域中是否存在b這個變量。 //右邊RHS查詢變量a的值,將a賦值給b。 var b = a; //返回a,b是RHS查詢變量a的值和變量b的值并使用。 return a + b; } //左邊LHS查詢變量c,查詢作用域中是否存在c這個變量。 //右邊RHS引用函數foo,將2作為參數傳進去。 var c = foo(2);
二、異常
關于異常要強調一點,必須在嚴格模式下。因為在非嚴格模式下,LHS查詢若是在最頂層的全局作用域上找不到查詢的變量,則會創建一個該名稱變量返還給引擎。
ReferenceError:同作用域判別失敗相關。(比如:作用域中遍尋不到所需的變量)
TypeError:作用域判別成功了,但是對結果的操作是非法或不合理的。(比如:試圖對一個非函數類型的值進行函數調用,或者引用null或undefined類型的值中的屬性)
舉個栗子:
"strict" function foo() { console.log(a) //undefined console.log(b) //ReferenceError } var a = 2;
聲明提升
一、初步了解
編寫javascript代碼時,很多時候都會覺得代碼會自上而下的執行。但是碰到聲明提升,這種想法就會被打破。
舉個栗子:
a = 2; var a; console.log(a); 運行結果為: 2
如果按照常理的自上而下執行,那么a執行的預期結果應當是undefined,然而為什么會是2?
這就是聲明提升的結果。
當初步了解聲明提升的時候,碰上下面的代碼:
console.log(a); var a = 2; 運行結果為:undefined
初步了解聲明提升之后,會自然而然的認為,聲明就會被提升,然而聲明的時候賦值,卻得不到變量的值。
其實,上面代碼的運行步驟可以分解為:
var a; //聲明提升 console.log(a); //打印a的值 a = 2; //對a進行賦值
原來,聲明提升就是字面上的聲明提升,其余的操作(如:賦值和其他邏輯)都還在原地踏步。
聲明一個函數進行相應的操作,會得到函數聲明提升的結果。由此可以發現:變量和函數的聲明都會被提升在其他代碼的前面執行。
通過幾次試驗可以逐步了解到,其實聲明提升就是:變量和函數的聲明會被提升在其他代碼(當前作用域)的前面執行。
走到這里,有人就會想到,要是函數表達式,也會進行提升嗎?
答案是:不會。而且,即使是具名函數表達式,在名稱標識符賦值之前也是不能使用的。
舉個栗子:
foo(); //TypeError bar(); //ReferenceError var foo = function bar(){};
代碼分解為:
var foo; //變量聲明提升 foo(); //foo對undefined值進行函數調用導致非法操作,故TypeError bar(); //bar函數并沒有聲明,故ReferenceError foo = function bar(){}; //對foo進行賦值
所以:函數表達式在名稱標識符賦值之前是不能使用的。
注意:1、每個作用域都會進行提升操作。(所以函數內部形成的作用域也會有提升操作,提升 操作僅限當前的函數內部作用域)
2、在函數和變量提升時,函數優先提升。
3、一個普通塊內部的函數聲明通常會被提升到所在的作用域的頂部。
在閱讀《你不知道的javascript》時,學習let的過程中,會發現有說明提到:使用let進行的聲明不會在作用域中進行提升。聲明的代碼在被運行之前是,聲明并不存在。
舉個栗子:
console.log(a); let a = 2; 運行結果是:ReferenceError: Cannot access 'a' before initialization. //初始化前無法訪問"a"
然后回到之前我運行的代碼,將let換為var,返回的結果是undefined。
二者結合,再加上閱讀我用了兩個月的時間才理解let這篇文章,發現對let是否提升有了一個更新的認識。
作者把js變量分成三部分操作:創建(create)、初始化(initialize)和賦值(assign)。
上面的操作之所以會有不同的響應并不是說let沒有創建,而是有一個初始化的過程并沒有執行。而在初始化之前使用變量,就會形成一個暫時性死區。
經過var和let和function的測試可以總結到:
var的創建和初始化被提升,賦值不會被提升。
let的創建被提升,初始化和賦值不會被提升。
function的創建、初始化和賦值均會被提升。
感謝各位的閱讀!看完上述內容,你們對javascript聲明提升是什么大概了解了嗎?希望文章內容對大家有所幫助。如果想了解更多相關文章內容,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。