理解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>
本教程向我们讲解了作用域和上下文。对代码进行作用域划分可以通过减少错误来提高效率并简化调试。它还可以优化命名冲突,因为我们可以将同一变量用于具有多个作用域的不同目的。
数据结构
网络
关系数据库管理系统 (RDBMS)
操作系统
Java
iOS
HTML
CSS
Android
Python
C语言编程
C++
C#
MongoDB
MySQL
Javascript
PHP