1.詞法作用域
就是定義在詞法階段的作用域,作用域查詢會在找到第乙個匹配的識別符號時停止。在多層的巢狀作用域中可以定義同名的標識 符,這叫作「遮蔽效應」(內部的識別符號「遮蔽」了外部的識別符號)。拋開遮蔽效應,作用域查詢始終從 執行時所處的最內部作用域開始,逐級向外或者說向上進行,直到遇見第乙個匹配的識別符號為止。
全域性變數會自動成為全域性物件(比如瀏覽器中的window物件)的屬性,因此可以不直接通 過全域性物件的詞法名稱,而是間接地通過對全域性物件屬性的引用來對其進行訪問。如:window.a通過這種技術可以訪問那些被同名變數所遮蔽的全域性變數。但非全域性的變數如果被遮蔽了,無 論如何都無法被訪問到。無論函式在**被呼叫,也無論它如何被呼叫,它的詞法作用域都只由函式被宣告時所處的位置決定。
2.欺騙詞法
function foo(str,a)
var b=2;
foo('var b=3;',1);//1,3
eval(...)經常被用來執行動態建立的**。
呼叫中的『var b=3;』,這段**會被當做本來就在那裡一樣來處理,由於那段**宣告了 乙個新的變數b,因此它對已經存在的foo(..)的詞法作用域進行了修改。事實上,和前面提到的原 理一樣,這段**實際上在foo(..)內部建立了乙個變數b,並遮蔽了外部(全域性)作用域中的同名 變數。
當console.log(..)被執行時,會在foo(..)的內部同時找到a和b,但是永遠也無法找到外部的b。因 此會輸出「1,3」而不是正常情況下會輸出的「1,2」。
but ....
function foo(str)
foo('var a=2');
在嚴格模式下,它就掙脫不了了。
with()通常被當作重複引用同乙個物件中的多個屬性的快捷方式,可以不需要重複引用物件本身。
var obj = ;
//這樣重複比較單調
obj.a = 2;
obj.b = 3;
obj.c = 4;
//快捷方式
with(obj)
function foo(obj)
}var o1=
var o2=
foo(o1);
console.log(o1.a)//2
foo(o2);
console.log(a2.a);//undefined
console.log(a);//2 a被洩露到全域性作用域上了
儘管with塊可以將乙個物件處理為詞法作用域,但是這個塊內部正常的var宣告並不會被 限制在這個塊的作用域中,而是被新增到with所處的函式作用域中。
o2的作用域、foo(..)的作用域和全域性作用域中都沒有找到識別符號a,因此當a=2執行時,自動建立 了乙個全域性變數(因為是非嚴格模式)。
詞法作用域意味著作用域是由書寫**時函式宣告的位置來決定的。編譯的詞法分析階段基本能 夠知道全部識別符號在**以及是如何宣告的,從而能夠**在執行過程中如何對它們進行查詢。
你不知道的JavaScript (上)
一 編譯的原理主要分為三個步驟 1 分詞 詞法分析 這個步驟主要是將字串分解成有意義的 2 解析 語法分析 陣列巢狀形成結構樹。3 生成 將結構樹轉化為 的過程。二 作用域 引擎主要進行搜尋查詢編譯等過程,分為左查詢lhs和右查詢rhs 編譯器主要是進行 的生成,語法分析。作用域主要是 確定訪問許可...
你不知道的JavaScript 筆記
作用域是什麼?作用域的兩種工作模式 詞法作用域和動態作用域 1.查詢 作用域查詢會在找到第乙個匹配識別符號停止 2.欺騙詞法 eval 修改作用域 with 建立新的作用域 後果 導致js引擎在靜態分析時停止優化,導致效能下降 遵循最小授權原則 1.隱藏內部實現 2.規避衝突 3.立即執行函式 ii...
你不知道的JavaScript 作用域(二)
詞法階段 詞法作用域是定義在詞法階段的作用域。欺騙詞法 欺騙詞法的兩個機制 1 eval function foo str,a var b 2 foo var b 3 1 結果是1,3function foo str foo var a 2 2 with var obj 單調乏味的重複 obj ob...