JS中执行环境与作用域的关系

【JS-TASK01】简述JS中执行环境与作用域的关系


1.背景介绍


核心概念
执行环境
环境栈
作用域链


2.知识剖析


执行环境是什么?
执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。 每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。 我们编写的代码是无法访问这个对象的,但解析器在处理数据时会在后台使用它。


全局执行环境
全局执行环境是最外围的一个执行环境,在Web浏览器中,全局执行环境被认为是window对象, 因此所有全局变量和函数都是作为window对象的属性和方法来创建的。 某个执行环境中的所有代码执行完毕后,该环境就会被销毁,保存在其中的所有变量和函数定义也随之销毁。


变量对象
如果所在环境是函数,那么就会把这个函数的活动对象作为变量对象(在函数中,变量对象==活动对象)。 一般而言,函数执行过程,可以分成两步:1.进入执行环境;2.执行代码。

环境栈是什么
环境栈的定义
当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。执行之后,再从环境栈中弹出。


原理解析
JavaScript解释器在浏览器中是单线程的,这意味着浏览器在同一时间内只执行一个事件, 对于其他的事件我们把它们排队在一个称为 执行栈的地方。 我们已经知道,当浏览器第一次加载你的script,它默认的进了全局执行环境。 如果在你的全局代码中你调用了一个函数,那么顺序流就会进入到你调用的函数当中, 创建一个新的执行环境并且把这个环境添加到执行栈的顶部。 如果你在当前的函数中调用了其他函数,同样的事会再次发生。 执行流进入内部函数,并且创建一个新的执行环境,把它添加到已经存在的执行栈的顶部。 浏览器始终执行当前在栈顶部的执行环境。一旦函数完成了当前的执行环境,它就会被弹出栈的顶部, 把控制权返回给当前执行环境的下个执行环境。

作用链是什么
作用链的定义
作用域链与一个执行上下文相关,是内部上下文所有变量对象(包括父变量对象)的列表,用于变量查询。 作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。


特点
代码在执行环境中执行时,执行环境会为变量对象创建作用域链。
作用域链是由变量对象组成的数据对象链。
作用域链的前端,始终是当前函数执行环境的变量对象。
作用域链的最后端,始终是全局执行环境的变量对象。


3.常见问题


问题1:函数的完整生命周期是怎样的?


4.解决方案


函数的创建(定义)
在一个函数被定义的时候, 会将它定义时刻的scope chain链接到这个函数对象的[[Scopes]]属性,函数可以通过这个属性来访问更高层的作用域。
[[Scopes]]是所有父变量对象的层级链,处于当前函数上下文之上,在函数创建时存于其中。
[[Scopes]]在函数创建时被存储--静态(不变的),永远永远,直至函数销毁。
[[Scopes]]存储的是定义时刻的作用域链,是函数本身所依赖的变量对象+其所在环境的[[Scopes]]组成的。


5.编码实战


6.扩展思考


标识符解析
标识符解析是沿着作用域链一级一级向上(外)搜索标识符的过程。搜索过程始终从作用域链的前端开始,然后逐级向后回溯,直至找到标识符为止。
其中内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部变量环境中的任何变量和函数。这些环境之间的练习是线性的,有次序的。每个环境变量都可以向上搜索作用域链,以查询变量和函数名;反之则是不行。


7.参考文献


参考一:执行环境与作用域

8.更多讨论


提问一 如何理解全局执行环境?
全局执行环境可以被认为是Windows对象也就是说所有全局变量和函数都是作为windows对象的属性和方法来创建的


提问二 作用域链与变量对象的关系是怎样的?
代码在执行环境中执行时,执行环境会为变量对象创建作用域链,
作用域链是由变量对象组成的数据对象链。


提问三  为什么内部环境可以通过作用域链访问外部环境,反之则不行?
标识符解析是沿着作用域链一级一级向上(外)搜索标识符的过程。这个过程是线性的,不可逆
 

猜你喜欢

转载自blog.csdn.net/qq_42247970/article/details/81074355