本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)
作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
执行上下文
执行上下文的概念在 JavaScript 中是颇为重要的,我理解是一种执行环境的一种对象化的体现,不能理解上下文是什么的时候,就当做对象来理解。变量或函数的上下文决定了它们可以访问哪些数据,以及它们的行为。它保存着函数执行所需的重要信息,有着三个重要属性:
- 变量对象(variable object)
- 作用域链(scope chain)
- this指针(this value)
全局上下文
在浏览器中,全局上下文就是我们常说的 window 对象,因此所有通过 var 定义的全局变量和函数都会成为 window 对象的属性和方法。(注意:使用 let 和 const 的顶级声明不会定义在全局上下文中,但在作用域链解析上效果是一样的)
变量对象
每个上下文都有一个关联的变量对象( variable object),而这个上下文中定义的所有变量和函数都存在于这个对象上。而每当一个函数执行之前,执行引擎都会为这个函数创建他的上下文对象,创建上下文对象的时候,就会创建它的重要属性 => 变量对象。创建变量对象的过程如下。
-
创建arguments对象。(全局上下文的变量对象没有arguments对象)
-
变量提升
- 找到函数内所有函数声明,存储在变量对象中,key是函数名,value是函数的引用。
- 找到函数内所有变量声明,存储在变量对象中,key是变量名,value是undefined。
上下文的生命周期在其所有代码执行完后结束,上下文对象被销毁,包括定义在它上面的所有变量和函数(全局上下文在应用程序退出前才会被销毁,比如关闭网页或退出浏览器)。
上下文栈
JS在执行的时候会维护一个上下文栈,每次开始执行一个函数之前,JS都要创建一个上下文对象,并将其压入上下文栈中。因此,当前正在执行的函数的上下文(简称当前上下文)总是在栈顶,这个函数一执行完,其上下文就会从栈中弹出,被销毁。将控制权返还给之前的执行上下文。这个执行栈就映射出执行的顺序。代码开始运行时,栈顶会先放入一个全局上下文(全局上下文同样有变量对象,作用域链和this指针)
作用域链
上下文中的代码在执行的时候,会创建变量对象的一个作用域链( scope chain)。这个作用域链决定了各级上下文中的代码在访问变量和函数时的顺序和范围。代码正在执行的上下文的变量对象始终位于作用域链的最前端。代码执行时的标识符(变量)解析是通过沿作用域链逐级搜索标识符名称完成的。搜索过程始终从作用域链的最前端开始,然后逐级往后,直到找到标识符。(这就是外层不能访问内层,内层可以访问外层的原因)
实例
var color = "blue";
function changeColor() {
if (color === "blue") {
color = "red";
} else {
color = "blue";
}
}
changeColor();
分析:函数 changeColor()的作用域链包含两个对象:一个是它自己的变量对象(就是定义 arguments 对象的那个),另一个是全局上下文的变量对象。这个函数内部之所以能够访问变量color,就是因为可以在作用域链中找到它。
感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。
写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤
「欢迎在评论区讨论,掘金官方将在掘力星计划活动结束后,在评论区抽送100份掘金周边,抽奖详情见活动文章」。