理解JavaScript中的函式作用域和上下文


在本教程中,我們將討論JavaScript中的函式作用域和上下文。

函式是Javascript的構建塊。因此,JavaScript是一種函數語言程式設計語言。

作用域

“作用域”是在函式中定義和使用變數的程式碼空間。作用域有四種類型。

全域性作用域

全域性“作用域”是預設作用域。具有全域性“作用域”的變數可在整個程式中訪問。關閉瀏覽器會刪除全域性變數。視窗物件可以訪問var變數,而不能訪問let變數。

函式作用域或區域性作用域

函式變數只能在函式內訪問。變數的建立和刪除發生在函式開始和結束時。函式引數充當區域性變數。

詞法作用域

巢狀函式只能在其父函式內訪問。子函式可以訪問父函式變數和全域性變數,而父函式不能訪問子函式變數。詞法作用域有助於避免不必要的變數重用。

塊作用域或模組作用域

ES6中的let和const關鍵字提供了塊作用域。{}塊內的變數只能在程式碼塊內訪問。var宣告不能提供塊作用域。if條件語句、for迴圈內的程式碼塊是塊作用域的示例。

使用者可以按照以下語法來使用作用域。

語法

/*Global scope*/
function functionName(){
   /*local scope*/
   if(condition){
      /*module scope*/
   }
   function nested(){
      /*lexical scope*/
   }
}

上面的語法是所有作用域的抽象。

示例

程式首先呼叫驅動程式函式。返回區域性變數作用域。接下來是迴圈執行,其中使用let關鍵字存在塊變數作用域。請注意,當我們在塊外部訪問此塊變數時,它會引發錯誤。

接下來是子函式執行。請注意,子函式可以使用詞法作用域訪問父變數。最後,我們在函式外部訪問全域性變數。在catch塊中訪問詞法變數s會引發錯誤。

<html> <body> <h2> Illustrates the function scope </h2> <p id="fnScopClsInp"></p> <div id="fnScopClsBtnWrap"> <button id="fnScopClsBtn"> Get Scope </button> </div> <br> <br> <p id="fnScopClsOut"></p> <script> var fnScopClsBtn = document.getElementById("fnScopClsBtn"); var fnScopClsBtnWrap = document.getElementById("fnScopClsBtnWrap"); var fnScopClsInp = document.getElementById("fnScopClsInp"); var fnScopClsOut = document.getElementById("fnScopClsOut"); var fnScopStr = ""; var globScope = "Global scope"; function functionScope() { var fnScope = "Local or functional scope"; fnScopStr += fnScope + "<br><br>"; function lexicalScope() { var lexScope = "Lexical scope"; for (var i = 0; i < 1; i++) { let blockScop = "Block or module scope"; fnScopStr += blockScop + "<br><br>"; } try { fnScopStr += blockScop + "<br><br>"; } catch (e) { fnScopStr += e + "<br><br>"; } function innerFunction() { var childFn = "Child function"; fnScopStr += childFn + "<br><br>"; fnScopStr += lexScope + "<br><br>"; } innerFunction(); } lexicalScope(); } fnScopClsBtn.onclick = function() { functionScope(); fnScopStr += globScope + "<br><br>"; try { fnScopStr += lexScope + "<br><br>"; } catch (e) { fnScopStr += e + "<br><br>"; } fnScopClsOut.innerHTML = fnScopStr; }; </script> </body> </html>

上下文

上下文是程式碼的環境或執行空間。“this”關鍵字表示上下文的使用。它在全域性上下文中返回視窗物件。

執行上下文

建立函式還會建立執行上下文。執行堆疊控制上下文的執行順序。作用域鏈從子函式到父函式再到全域性作用域。存在兩種執行上下文:全域性執行上下文和區域性執行上下文。執行上下文有兩個階段:建立階段和執行階段。

函式上下文

可以使用“this”關鍵字訪問函式上下文。嚴格模式下的函式引用返回undefined。在正常模式下,函式返回視窗物件。當物件具有方法時,“this”關鍵字返回該物件。

使用call()、apply()或bind()呼叫函式是另一個上下文示例。唯一的區別是引數更改。函式bind()將引數繫結到新的函式上下文。

使用者可以按照以下語法來使用“上下文”。

語法

function objContext(){
   const objVar ={
      objFn: function(){
         return this;//object context
      }
   };
}
function functionD(){
   "use strict";
   return this;//undefined context
}
function functionC(){
   return this;//window context
}

此程式碼片段中包含一些上下文語法。

示例

在此程式中,執行堆疊如下。堆疊彈出上下文B,然後是上下文A,最後是全域性上下文。

函式內的“this”關鍵字返回物件視窗上下文。在嚴格模式下會發生未定義上下文。

全域性上下文正在訪問全域性變數。使用call()和bind()呼叫函式是其他上下文。

<html> <body> <h2> Illustrating the function context </h2> <p id="fnContxtClsInp"></p> <div id="fnContxtClsBtnWrap"> <button id="fnContxtClsBtn">Get context</button> </div> <br> <br> <p id="fnContxtClsOut"></p> <script> var fnContxtClsBtn = document.getElementById("fnContxtClsBtn"); var fnContxtClsBtnWrap = document.getElementById("fnContxtClsBtnWrap"); var fnContxtClsInp = document.getElementById("fnContxtClsInp"); var fnContxtClsOut = document.getElementById("fnContxtClsOut"); var fnContxtStr = ""; var context = "context global"; function objContext() { const objVar = { objFn: function() { return this; }, context: "context object" }; function nestedContext() { return this.context } fnContxtStr += nestedContext() + "<br><br>"; fnContxtStr += "context call " + nestedContext.call(objVar) + "<br><br>"; fnContxtStr += "context bind " + nestedContext.bind(objVar) + "<br><br>"; } function functionD() { "use strict"; return this; } function functionC() { return this; } function functionB() { fnContxtStr += "context B pops first<br><br>"; } function functionA() { functionB(); fnContxtStr += "context A pops second<br><br>"; } fnContxtClsBtn.onclick = function() { functionA(); fnContxtStr += "context global pops finally<br><br>"; fnContxtStr += "context " + functionC() + "<br><br>"; fnContxtStr += "context " + functionD() + "<br><br>"; objContext(); fnContxtClsOut.innerHTML = fnContxtStr; }; </script> </body> </html>

本教程向我們講解了作用域和上下文。對程式碼進行作用域劃分可以透過減少錯誤來提高效率並簡化除錯。它還可以最佳化命名衝突,因為我們可以將同一變數用於具有多個作用域的不同目的。

更新於:2022年11月15日

219 次瀏覽

啟動您的職業生涯

完成課程獲得認證

開始
廣告
© . All rights reserved.