js作用域,执行环境(二)
作用域链
1.创建/声明
作用域链是与执行环境相关的。在JavaScript中,“一切皆对象”,而函数的这个对象有一个内部属性[[scope]]
,该内部属性指向了该函数的作用域链,而作用域链中存储了每个执行环境相关的变量对象。
每当声明或者创建一个函数的时候,那么会创建这个函数的作用域链,但是注意.此时这个作用域链只包含一个变量对象(window/global object全局对象).
2.执行阶段
当函数被调用的时候,就会创建一个新的执行环境.然而解释器的内部,每次调用执行环境会有两个阶段:
2.1创建阶段
当函数被调用,但是未执行内部代码之前:
1.创建变量对象(VO),由变量、函数声明、和参数组成.
2.确定this指向.
3.初始化(建立)作用域链(scope chain),相对这个新的执行环境.
什么是变量对象
变量对象是与执行上下文对应的概念,定义着执行上下文下的所有变量、函数以及当前执行上下文函数的参数列表。也就是说变量对象定义着一个函数内定义的参数列表、内部变量和内部函数。
数据结构上来说,它是这样的:
变量对象的创建过程
1 | function outerFun (arg1, arg2) { |
它的变量对象创建过程是这样的:
这个创建变量对象的过程实际就是函数内数据(函数参数、内部变量、内部函数)初始化的过程。
2.2激活/执行阶段
赋值,引用函数,解释/执行代码。
进入执行阶段之后,变量对象转变(VO)为了活动对象(AO),里面的属性都能被访问了,然后开始进行执行阶段的操作。所以活动对象实际就是变量对象在真正执行时的另一种形式。
这个对象(活动)就会被存储在该函数的[[scope]]
属性所指向的作用域链中,而之前的对象就被压在了新的变量对象的下边,这个可以类比栈,新的变量对象就放在了栈的最顶端,给最顶端的序号为0,向下以此类推,有点像倒金字塔模型
1 | var a = 8; |
当以后我们需要查找变量的时候,就总是会沿着这个作用域链的顶端(序号0/栈顶)开始查找,一直到作用域链(栈底)的末端,直到找到为止。也就是说顶端的活动对象可以访问到其后面的参数.