一、作用域
定义:
作用域[[scope]]: 每个js函数都有一个对象,对象中有些属性我们可以访问,有些不可以,这些属性仅供js引擎存取,[[scope]]就是其中一个,[[scope]]指的就是我们所说的作用域,其中存储了运行期上下文的集合,即作用域决定了代码区域块中变量和其他资源的可见性。
域类型:
- 全局作用域:贯穿js文档,所用地方可访问;
- 局部作用域:
- 函数作用域:函数内形成AO对象,外部无法访问;
- 块级作用域(无,es6有该概念)
二、作用域链
定义:
作用域链:[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。
执行期上下文定义:
当函数执行时,会创建一个称为执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,执行上下文被销毁。
三、举例
列举下边的例子来说明作用域链:
| function fn ( ) {
function b ( ) {
var b = 2;
}
var a = 1;
b( );
}
fn( ); | | —- |
fn在被创建时:会生成一个[[scope]]属性,这个属性有一个集合GO,被存储在[[scope]]域中的顶端,假设地址为0。如下图:
fn在被执行的时候,fn会预编译,创建一个AO对象(执行期上下文)被存储在fn[[scope]]域的最顶端,假设地址为0,这时GO对象的地址为1,如下图:
执行fn时,创建了函数b( ),b在创建时,生成[[scopw]],直接‘拿’fn的环境(域)当做自己的域:如下图:
执行b()时,b会创建自己AO对象,存储在域中的最顶端。如下图:
画的有点磕碜,见谅~
b函数执行完会和自己执行时生成的AO分手,砍掉该作用域链,回到b创建时的‘样子’,这是b的scope-chain中剩下两条链a函数的AO和GO。
a函数执行完时会和自己执行时产生的AO分手,砍掉该作用域链,回到a创建时的’样子’,这是a的scope-chain中剩下GO
而变量的访问是按照作用域链自顶而下开始查找的,so,let’s go~
function a () {
function b () {
x = 0;
}
var x = 1;
b();
console.log(x) // 0
}
如有不对,欢迎指正
