作用域链

作用域链

当函数被执行,便进入了自己的执行上下文,
该执行上下文中的变量若并没有被找到,
就会往上一层的作用域中去查找。
直到该作用域的顶层(一般为全局环境中)

JS权威指南中有一句很精辟的描述: ”JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里.”

由上可知,作用域链的规则确定,是函数在哪里声明在地方,而非被执行的作用域中。
可以将此过程理解为,js引擎在解析js代码的时候就确定了函数的作用域链规则,而非是执行时产生的执行上下文而确定的作用域链。

函数被声明时

当函数被声明的时候,其函数内部有一个[[scope]]的属性,里面保存了该父作用域链级规则。

函数声明和执行的过程

以下为例

var scope = "global scope";
function checkscope(){
    var scope2 = 'local scope';
    return scope2;
}
checkscope();
  1. checkscope函数被创建时,作用域链相关规则被保存到内部属性[[scope]]中
checkscope.[[scope]] = [
    globalContext.VO
];
  1. 执行checkscope函数,checkscope函数创建上下文(checkscopeContext)。checkscopeContext被push进执行上下文栈中,以便执行代码。

  2. checkscope函数并不马上执行,而是初始化活动对象,加入形参、函数声明、变量声明,复制作用域链并将活动对象压入 checkscope 作用域链顶端

checkscopeContext = {
    AO: {
        arguments: {
            length: 0
        },
        scope2: undefined
    },
    Scope: checkscope.[[scope]],
}

将活动对象压入 checkscope 作用域链顶端

checkscopeContext = {
    AO: {
        arguments: {
            length: 0
        },
        scope2: undefined
    },
    Scope: [AO, [[Scope]]]
}
  1. 始执行函数,随着函数的执行,修改 AO(变量对象) 的属性值
checkscopeContext = {
    AO: {
        arguments: {
            length: 0
        },
        scope2: 'local scope'
    },
    Scope: [AO, [[Scope]]]
}
  1. 执行完函数,并从执行上下文栈中弹出。

作用域和执行上下文

  • 作用域规定了函数内部变量,和内部函数的可访问范围。js没有块级作用域,当生命一个函数的时候,就产生了一个局部作用域。是一套规则
  • 而执行上下文是,当函数在执行的时候,不仅仅是作用域和作用域链的访问规则。而是包括活动变量,形参等等的AO的环境。
作用域链的规则,是当该函数在执行的时候,在自己本身的AO(变量对象)中找不到该变量,便遵循作用域链的规则往父作用域(该函数声明的地方就是其父作用域)中AO中寻找,该作用域链寻找一直到全局作用域中。

你可能感兴趣的:(作用域链)