javaScript作用域和作用域链详解

作用域就是一个变量或者函数能够访问到区域。
ES5并没有块级作用域,在ES2015中已经新增块级作用域。
实例代码:

var name = " 清风明月 "function mainA(){
    var name = "qingfeng";
    console.log(name);
}
mainA();  //结果:qingfeng
console.log(name); //清风明月

在上面的代码中,第一个name变量属于全局作用域,在代码中的任何位置都可以访问。
第二个name属于函数作用域,只能够在mainA()中使用,并且局部作用域变量可以覆盖它上层作用域同名变量。

var name = " 清风明月 "function mainA(){
    // var name = "qingfeng";
    console.log(name);
}
mainA();  //结果:清风明月
console.log(name); //结果:清风明月

函数内部的name声明已经被删除,那函数是如何找到全局作用域上的name的?
ECMAScript中有一个重要的概念:作用域链(scope Chain),每一个执行上下文都会关联一个作用域链。

函数后面加多个()是什么意思?
f()是执行f函数,返回子函数
f()()是执行子函数,返回孙函数
f()()()是执行孙函数

我们可以认为作用域链是当前执行上下文的一个属性,它指向一个变量对象堆栈。

function mainA(){
       function mainB(){
            //code
    }
    return mainB();
}
mainA()();
mainB函数上下的作用域可以表示为如下:
Scope = [
    AO(mainB),
    AO(mainA),
    VO(global)
]

当查找一个变量的时候,首先会在AO(mainB)中查找,如果没有则上溯到AO(mainA)查找,以此类推。
更准确的说每一个function函数都有一个内部[[scope]]指针,它指向一个变量对象堆栈。
也就是说作用域链Scope = 当前AO + [[scope]].
强调:在作用域和作用域链在创建时就已经确定

变量对象VO 和 活动对象AO
变量对象VO:是与执行上下文相关的特殊对象,用来存储上下文的函数声明,函数形参和变量。在global全局上下文中,变量对象也是全局对象自身,在函数上下文中,变量对象被表示为活动对象AO。

活动变量AO:当函数被调用后,这个特殊的活动对象就被创建了。它包含普通参数与特殊参数对象(具有索引属性的参数映射表)。活动对象在函数上下文中作为变量对象使用。
在函数执行上下文中,VO是不能直接访问的,此时由活动对象(activation object,缩写为AO)扮演VO的角色。

猜你喜欢

转载自blog.csdn.net/xiaoxia188/article/details/80800819