作用域是什麼? 作用域是什麼? 答:在《你不知道的javascript》書中提到,作用域就是根據名稱查找變數的一套規則。古語有“無規矩不成方圓”,但是沒有方圓,規矩又給誰用?所以個人理解作用域就是“規矩”+”方圓“。 書中提到作用域共有兩種主要的工作模型。第一種是詞法作用域,另外一種叫作動態作用域。 ...
-
作用域是什麼?
答:在《你不知道的javascript》書中提到,作用域就是根據名稱查找變數的一套規則。古語有“無規矩不成方圓”,但是沒有方圓,規矩又給誰用?所以個人理解作用域就是“規矩”+”方圓“。
書中提到作用域共有兩種主要的工作模型。第一種是詞法作用域,另外一種叫作動態作用域。
詞法作用域是由你在寫代碼時將變數和塊作用域寫在哪裡來決定的,因此當詞法分析器處理代碼時會保持作用域不變(大部分情況下是這樣的)。無論函數在哪裡被調用,也無論它如何被調用,它的詞法作用域都只由函數被聲明時所處的位置決定。。
欺騙詞法作用域有兩種方法:eval(...)(非嚴格模式),with(...);
-
誰有作用域?
答:全局。
函數:本質上,聲明在一個函數內部的變數或函數會在所處的作用域中“隱藏”起來,外部作用域無法訪問包裝函數內部的任何內容。
塊作用域:指的是變數和函數不僅可以屬於所處的作用域, 也可以屬於某個代碼塊(通常指 { .. } 內部)
for (var i=0; i<10; i++) { console.log( i ); }
上述代碼中,我們只是想定義一個在for內部使用的i變數,但事實上i變數已經污染到了整個作用域,所以從錶面上看,JS並沒有塊作用域的相關功能。但我們深入研究呢?
with:用 with 從對象中創建出的作用域僅在 with 聲明中而非外 部作用域中有效。
try/catch:catch 分句會創建一個塊作用域,其中聲明的變數僅在 catch 內部有效。
ES6:let:let 關鍵字可以將變數綁定到所在的任意作用域中(通常是 { .. } 內部)。
但是由於 let 聲明附屬於一個新的作用域而不是當前的函數作用域(也不屬於全局作用域), 當代碼中存在對於函數作用域中 var 聲明的隱式依賴時,就會有很多隱藏的陷阱,如果用 let 來替代 var 則需要在代碼重構的過程中付出額外的精力。
const:可以用來創建塊作用域變數,但其值是固定的 (常量)。之後任何試圖修改值的操作都會引起錯誤。
-
為什麼要有作用域?
答:1. 作用域的最大用處就是隔離變數,不同作用域下同名變數不會有衝突。舉個例子:XXX縣下麵有一個王家莊,一個李家莊,王家莊和胡家堡各有一個李家,兩家都有一個叫小明的兒子,胡家堡的老李家給自家小明說了個叫王小翠的媳婦。胡家堡的李小明很開心,挑了個黃道吉日準備去派處所把小翠的戶口遷到自家,試想,如果沒有王家莊和胡家堡之分,xxx縣派處所的民警就會很懵逼,兩個李小明,王小翠戶口遷誰家???有了王家莊和胡家堡的區分,這事就很好辦了。
2.最小特權原則:在軟體設計中,應該最小限度的暴露必要內容,而將其他內容都“隱藏”起來,比如某個模塊或對象的 API 設計。
-
JS引擎進入作用域會發生什麼?
答:JS引擎進入作用域,編譯器就會開始工作,它會執行兩輪操作(註意:進入不同的作用域都會觸發同樣的操作,這也是執行環境壓棧和出棧的由來):
-
初始化變數 :聲明參數並初始化,局部變數聲明,函數聲明並初始化,將這些變數保存到環境變數對象當中,
- 執行代碼:產生執行環境(執行環境在執行時才產生),當變數出現在賦值操作的左側時進行 LHS 查詢,出現在右側時進行 RHS 查詢。(RHS 查詢與簡單地查找某個變數的值別無二致,而 LHS 查詢則是試圖找到變數的容器本身,從而可以對其賦值。不成功的 RHS 引用會導致拋出 ReferenceError 異常。不成功的 LHS 引用會導致自動隱式地創建一個全局變數(非嚴格模式下),該變數使用 LHS 引用的目標作為標識符,或者拋 出 ReferenceError 異常(嚴格模式下)。如果 RHS 查詢找到了一個變數,但是你嘗試對這個變數的值進行不合理的操作, 比如試圖對一個非函數類型的值進行函數調用,或著引用 null 或 undefined 類型的值中的屬性,那麼引擎會拋出另外一種類型的異常,叫作 TypeError。)
-
作用域鏈是什麼?
答:當前作用域-->上一級作用域-->...-->全局作用域
-
誰有作用域鏈?
答:作用域嵌套的時候
-
為什麼要有作用域鏈?
答:首先需要瞭解一個概念:自由變數:在A作用域中使用的變數x,卻沒有在A作用域中聲明(即在其他作用域中聲明的),對於A作用域來說,x就是一個自由變數。
自由變數的取值需要到創建它的作用域,正因為這樣,所以才有了作用域鏈的出現。
書中是這樣說的:LHS 和 RHS 查詢都會在當前執行作用域中開始,如果有需要(也就是說它們沒有找到所需的標識符),就會向上級作用域繼續查找目標標識符,這樣每次上升一級作用域,最後抵達全局作用域,無論找到或沒找到都將停止。舉個例子:現實生活中我們經常看到尋人啟事(請原諒我舉這個令人悲憤的例子),尋找一個人,會在自己家找,自己家沒有,會到村,鎮,縣,市,... 由此會構成一個家-->村-->鎮-->縣-->市-->...的尋找鏈。也就是說作用域鏈的主要目的就是自由變數的取值。