1.函数执前
函数被定义时,就会创建函数的作用域 执行前的预编译会创建一个独一无二的AO对象,该对象中存有该函数中定义的变量和函数, 例如下列函数A的AO对象
function A(){
var a = 4
}
AO对象创建,将A函数中定义的变量名为AO对象的属性名,值为AO对象对应属性的值(这里涉及预编译,简单介绍下)
AO:{
a: 4;
}//A的AO对象
2.函数执行时
函数每执行一次就会创建一个AO对象 咱们不妨假设为开始有一个函数,定义时创建作用域然后预编译创建了AO对象A 当函数执行时函数内部也会有其他函数被定义然后产生作用域创建AO对象,假设为B 依次下去会有AO对象C,D...
function A() {
var a1 = 1
function B() {
var b = 2
function C() {
var c = 3
function D() {
var D = 4
}
}
}
}
A{B{C{D}}} 作用域链就是这些AO对象的集合形成的一个链式结构如下
graph TD
D-->C--> B-->A
3. 函数执行后
最新被创建AO对象的在作用域链的顶端,最先被执行, 能访问之前创建AO对象函数的作用域,函数被执行完就会被销毁,然后依次下去 所以作用域链中较早创建AO对象的函数不能访问之后创建AO对象函数的作用域 本例来说D最新创建能访问之前的A,B,C的作用域当A执行完被销毁后就变成
graph TD
C--> B-->A
D后面创建AO对象的作用域C,B,A已经找不到D的作用域了
function A() {
var a = 1
function B() {
var b = 2
console.log(a)
console.log(b) //3.B只能能访问A和自己函数中定义的变量
function C() {
var c = 3
console.log(b)
console.log(c)
console.log(a) // //2.C只能能访问A,B和自己函数中定义的变量
function D() {
var D = 4
console.log(b)
console.log(c)
console.log(a) //1.D能访问A,B,C和自己函数中定义的变量
}
}
}
}
[[scope]]
而这样的作用域链就储存在函数的属性[[scope]](作用域)中,是不可访问的
总结
当函数执行的时候,会创建一个称为执行期上下文的内部对象(ao对象) 所以多次调用一个函数会导致创建多个执行期上下文,当函数执行完毕,它所产生的执行期上下文会被销毁。 执行期上下文对象的集合呈链式连接储存在函数属性[[scope]](作用域中)中,这就是作用域链。