作用域
在调用栈中创建出了执行上下文,我们称这个上下文为作用域(函数会给自己创建作用域)
当函数执行时会创建一个成为执行期上下文的内部对象,一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应得执行上下文都是独一无二的,所以调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文会被销毁
作用域链
[[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{ }
| 作用域链 | |
|---|---|
| 0 | bAO |
| 1 | aAO |
| 2 | GO |
| GO | |
|---|---|
| this | window |
| golb | 100 |
| a | function |
| aAO | |
|---|---|
| this | window |
| a | 111 |
| b | function |
| arguments(函数自带) |
| bAO | |
|---|---|
| this | window |
| b | 222 |
| arguments(函数自带) | |
| --- | --- |