作用域和作用域链(不理解的评论)

·  阅读 620

作用域

在调用栈中创建出了执行上下文,我们称这个上下文为作用域(函数会给自己创建作用域)

当函数执行时会创建一个成为执行期上下文的内部对象,一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应得执行上下文都是独一无二的,所以调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文会被销毁

作用域链

[[scope]]中存储的执行期上下文对象的集合,这个集合呈链式连接,我们把这种链式连接叫做作用域链

我们先看代码:

function a(){
    function b(){
        var b=222
    }
    var a=111
    b()
    console.log(a);
}
var glob = 100
a()
复制代码

首先我们看代码,代码是一行行执行下去的。

我们来复习一下作用域:先是全局作用域GO 创建一个GO对象:找形参和变量声明,将形参和变量声明作为GO对象的属性名,值为undefined

GO{
Glob:undefined

}
复制代码

全局局里的函数声明,将函数名作为GO的属性名,值赋予函数体

GO{
Glob:undefined
a:function
}
复制代码

再看函数体:找形参和变量声明,将形参和变量声明作为AO对象的属性名,值为undefined

AO{
a:undefined
b:undefined
}
复制代码

将实参和形参统一(也就是把实参的值赋给形参)

AO{
a:undefined
b:undefined
}
复制代码

在函数体里找函数声明,将函数名作为AO的属性名,值赋予函数体

AO{
a:undefined
b:undefined,function
}
复制代码

代码执行:

GO{
Glob:undefined,100
a:function   }
AO{
a:undefined,111
b:undefined,function,222
}
复制代码

因为console.log(a)在函数体所以先在AO里寻找a的值,a=111所以输出111

下面我们来看看作用域链:

a 定义 a.[[scope]]-------->0:GO{ }

a 执行 a.[[scope]]-------->0:a:AO{ } 1:GO{ }

b 定义 b.[[scope]]-------->0:AO{ } 1:GO{ }

b 执行 b.[[scope]]-------->0:b:AO{ } 1:a:AO{ } 2:GO{ }

作用域链
0bAO
1aAO
2GO
GO
thiswindow
golb100
afunction
aAO
thiswindow
a111
bfunction
arguments(函数自带)
bAO
thiswindow
b222
arguments(函数自带)
------
分类:
前端
标签: