Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

深入理解作用域链 #5

Open
18888628835 opened this issue Feb 26, 2021 · 0 comments
Open

深入理解作用域链 #5

18888628835 opened this issue Feb 26, 2021 · 0 comments

Comments

@18888628835
Copy link
Owner

当JavaScript代码执行一段可执行代码(executable code)时,会创建对应的执行上下文(execution context)。
每个执行上下文包含三个重要属性

  • 变量对象
  • 作用域链
  • this

当查找变量时,首先从当前上下文中的变量对象查找,如果没有就会往上查找父级作用域中的变量对象,最后的终点是访问最外层上下文中的变量对象,如果没有就报错。这样由多个执行上下文的变量对象构成的链表就叫做作用域链。

当执行一段全局代码时,就会生成一个执行上下文,里面会包含全局变量对象

var a=123

globalContext.VO={
     a:123
}

函数书写

当书写一段函数代码时,就会创建一个词法作用域,这个作用域是函数内部的属性,我们用[[scope]]表示,它里面保存父变量对象,所以[[scope]]就是一条层级链。

function fn(){
}
/*
fn.[[scope]]=[
     globalContext.VO
]
*/

函数调用

当函数调用,就意味着函数被激活了,此时创建函数上下文,创建活动对象,然后将活动对象(AO)推到作用域链的前端。
我们用scope来表示此时的作用域

fnContext={
     Scope:[AO,fn.[[scope]]]
}

结合例子

我们来分析以下代码函数上下文中的变量对象和作用域的创建过程

var scope = "global scope";
function checkscope(){
    var scope2 = 'local scope';
    return scope2;
}
checkscope();

1、全局上下文创建,生成全局变量对象VO,checkscope函数创建,生成内部属性[[scope]],并且把父变量对象放进去。

checkscope.[[scope]]=[
     globalContext.VO
]

2、函数调用了,创建函数上下文并压入执行栈

ECStack=[globalContext,checkscopeContext]

3、函数调用的分析阶段,做准备工作,第一步:复制函数[[scope]]属性创建作用域链

checkscopeContext={
     Scope:checkscope.[[scope]]
}

4、第二步:创建活动对象,初始化活动对象,加入形参、函数声明、变量声明

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

5、第三步:将活动对象压入 checkscope 作用域链顶端

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

6、准备工作做完,开始执行函数,随着函数的执行,修改 AO 的属性值

checkscopeContext = {
    AO: {
        arguments: {
            length: 0
        },
        scope2: 'local scope'
    },
    Scope: [AO, [[Scope]]]
}

7.查找到 scope2 的值,返回后函数执行完毕,函数上下文从执行上下文栈中弹出

ECStack = [
    globalContext
];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant