這篇文章帶給大家的內容是關於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、一個普通區塊內部的函數宣告通常會被提升到所在的作用域的頂端。
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的建立、初始化和賦值都會被提升。
這篇文章到這裡就已經全部結束了,更多其他精彩內容可以關注PHP中文網的JavaScript教學影片專欄!
#以上是javascript聲明提升的介紹(附範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!