js作用域中的那些事兒(you don‘t know javascript)

在《你不知道的javascript(上)》中,瞭解到javascript在代碼執行前會先對代碼進行編譯,引擎查找變量的過程中提到了LHS查詢和RHS查詢兩個概念,下面就簡單談一下自己對其的理解:

LHS查詢:在查找變量中,如果查找的目的是爲了給變量賦值(“=”),就會執行LHS查詢。

RHS查詢:在查找變量中,如果查找的目的是爲了找到該變量是啥,就會執行RHS查詢。

那麼什麼是作用域呢,作用域是有什麼決定的呢?

書中的解釋是“根據名稱查找變量的一套規則”,說白了就是引擎是怎麼查找變量的,是在哪裏,按照什麼樣的規則找到該變量的--從當前的執行作用域開始查找變量, 如果找不到,就向上一級繼續查找。 當抵達最外層的全局作用域時, 無論找到還是沒找到(代碼執行就會報錯), 查找過程都會停止。作用域是由書寫代碼時,函數(或者變量)的位置決定的。

變量提升(只有變量聲明本身被提升,而其他部分包括運行邏輯和賦值被留到了原地)

var a = 3;

JavaScript 引擎首先會在代碼執行前對其進行編譯, 在這個過程中, 像 以上這樣的聲明會被分解成兩個獨立的步驟:變量的聲明和對變量進行賦值

變量聲明:在作用域中聲明變量var a;這個過程會發生在代碼(一切的處理邏輯)執行之前(最前面),也就是傳說中的變量提升;

變量賦值:a=3是在代碼執行的過程中進行的(LHS查詢,因爲這是一個賦值的過程,會查詢變量a並對其進行賦值);

例如:下面的代碼會報錯:

function foo(a) {
    console.log(a + b);
    b = a;
}
foo(2);
因爲在執行console的時候會查找b,但是找不到因爲根本就沒有聲明該變量;所以...,再看下面的例子:

function foo(a) {
    console.log(a + b);
   var  b = a;
}
foo(2);

這個結果會返回NaN,這個例子和上面的例子唯一的不同就是 b =  a變成了 var b = a;雖然只是前面多了一個var,但是正式這個 var b = a;引擎解析的時候是分成了兩部分var b(在執行console之前會執行)和b=a;RHS查詢的時候找到了該變量,但是還是不知道這個變量是啥(LHS查詢失敗);

函數聲明會被提升到普通變量聲明之前,例如

foo();//3
 function foo(){//函數聲明
 	alert(1)
 }
 var foo = function(){
 	alert(2)
 }

function foo(){//函數聲明
	alert(3)
}
爲什麼是3,而不是其他?因爲其實上述代碼的執行順序是這樣的:

function foo(){//函數聲明
 	alert(1)
 }

 function foo(){//函數聲明
	alert(3)
}
 var foo;
foo();//3

 foo = function(){
 	alert(2)
 }
 foo()//2

注:其實 "a is not defined"和undefined是不一樣的錯誤,前者是在全局作用域中都沒有找到a這個變量,才報的錯誤;後者是找到該變量了,但是沒有找到該變量的值(RHS查詢,相當於var a;)

"在函數內部定義的私有變量,當函數運行結束的時候已經銷燬了",也就是不存在了,因爲函數內部的私有變量的生命週期隨着函數的運行結束而結束(也就是說變量只存在於函數於逆行的時候),所以.....

“在軟件設計領域,應該最小的暴露必要的內容,將其他部分都隱藏起來”也叫最小暴露原則,因此可以需要隱藏的變量放在一個自運行的函數裏,這樣,只有該函數內部能訪問該變量,其他函數都訪問不到。

什麼叫自運行函數?就是突破傳統的調用方式的函數,建議類似於這樣:

(function fname(elem1,elem2){
		alert(elem1+elem2)
	})("hehe","haha")
在這裏,“elem1”,“elem2”是形參,“hehe”,“haha”是實參,當然你也可以不傳參。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章