JavaScript学习笔记(六):作用域与作用域链
JavaScript的函数是一个特殊的对象,它也有一些属性,如function.name
其中,有一个特殊的属性叫function.[[scope]]
,它存储着函数的作用域。对于[[scope]]属性的解释如下:
每个Javascript函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供Javascript引擎存取,[[scope]]就是其中一个。
[[scope]]指的就是我们所说的作用域,其中存储了执行期上下文的集合。
那什么是执行期上下文呢?
执行期上下文:
当函数执行时,会创建一个称为执行期上下文的内部对象(就是预编译里的AO对象、GO对象)。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被销毀。
每个函数被创建时都会创建执行期上下文,同时也会产生一个作用域链。什么是作用域链?
作用域链就是指[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。
函数被定义时,将GO放入作用域链的顶端
函数执行时将AO插入到GO的前面,此时AO位于作用域链的顶端
在查找变量时,从作用域链的顶端依次向下查找
举例:
function a(){
function b(){
var b = 123;
}
var a = 456;
b();
}
var glob = 100;
a();
在上述代码中,
a函数被定义时,作用域链发生如下变化:
a函数执行时,作用域链发生如下变化:
b函数被定义时,作用域链发生如下变化:
b函数执行时,作用域链发生如下变化:
作用域链变化总览:
在作用域链里,只有顶部的执行期上下文对象是函数自身创建的,其余的都是引用的。引用值有数据同步改变的特点。
数据同步改变的举例说明:
fucntion a(){
function b(){
var bb = 123;
aa = 0;
}
var aa = 456;
b();
console.log(aa);
}
var glob = 100;
a();
console.log(aa);
的输出结果为0,因为b函数是引用了a函数的AO对象,而aa是a函数的AO对象的属性,当b函数改变aa的值之后,在a函数访问aa时,显然访问结果是aa的改变后的值。
这说明了b函数里引用的a函数AO对象,和a函数自身创建的AO对象是同一个。