理解JavaScript中的函式作用域和上下文
在本教程中,我們將討論JavaScript中的函式作用域和上下文。
函式是Javascript的構建塊。因此,JavaScript是一種函數語言程式設計語言。
作用域
“作用域”是在函式中定義和使用變數的程式碼空間。作用域有四種類型。
全域性作用域
全域性“作用域”是預設作用域。具有全域性“作用域”的變數在整個程式中都是可訪問的。關閉瀏覽器會刪除全域性變數。Window物件可以訪問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”關鍵字表示上下文。它在全域性上下文中返回window物件。
執行上下文
建立函式也會建立執行上下文。執行堆疊控制上下文的執行順序。作用域鏈從子函式到父函式再到全域性作用域。存在兩種執行上下文:全域性執行上下文和區域性執行上下文。執行上下文有兩個階段:建立階段和執行階段。
函式上下文
可以使用“this”關鍵字訪問函式上下文。嚴格模式下的函式引用返回undefined。在普通模式下,函式返回window物件。當物件具有方法時,“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”關鍵字返回物件Window上下文。在嚴格模式下會發生未定義的上下文。
全域性上下文正在訪問全域性變數。使用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>
本教程教我們作用域和上下文。對程式碼進行作用域限定可以提高效率,減少錯誤,並簡化除錯。它還可以最佳化命名衝突,因為我們可以將同一個變數用於多個作用域以實現不同的目的。
資料結構
網路
關係資料庫管理系統 (RDBMS)
作業系統
Java
iOS
HTML
CSS
Android
Python
C語言程式設計
C++
C#
MongoDB
MySQL
Javascript
PHP