深入JavaScript作用域

理解作用域是理解JavaScript的关键所在,作用域可以确定哪些变量可以被函数访问,以及确定this的值。每个JavaScript函数都是Function对象的一个实例,Function对象有一个内部属性[[Scope]],此属性只能被JavaScript引擎存取。通过[[Scope]]属性可以访问函数的作用域链,进而决定哪些数据可以被函数访问。如下代码:

<script language="javascript" type="text/javascript">
function add(value1, value2) {
return value1 + value2;
}
</script>

当函数add()被创建时,它的作用域链(只是简单的写出了几个全局对象)如图所示

当add()执行时,会创建一运行时上下文(execution context)的内部对象,一个运行时上下文定义了一个函数执行的环境。函数每次执行时的运行时上下文都是不同的,所以多次调用就会导致多个运行时上下文的创建与销毁。当函数执行完毕,运行时上下文就被销毁。每个运行时上下文都有自己的作用域链,用于标示符解析。当运行时上下文被创建时,它的作用域链初始化为当前函数的[[Scope]]属性中所包含的对象。这些值按照他们出现在函数中的顺序,被复制到执行上下文的作用域链中。这个过程一旦完成,一个被称作“活动对象(Active object)的新对象就被创建好了。当运行时上下文被销毁时,活动对象也随之被销毁。

当调用代码 var result=add(1,2) 时的运行时上下文和作用域链如图:

闭包是JavaScript强大特性之一,通俗的讲闭包就是一个可以访问另一个函数作用域中变量的函数。如下代码:

<script language="javascript" type="text/javascript">
function add(value1, value2) {
return function () {
return value1 + value2;
} ();
}
</script>

这个方法内有一匿名方法,可以访问add()方法的作用域中的参数value1和value2。当执行add(1,2)时的运行时上下文的作用域链和闭包如下

通常来说,函数的活动对象会随运行时上下文一同销毁,但是使用闭包时,活动对象的引用仍存在于闭包[[Scope]]属性中,所以活动对象无法被销毁。当闭包执行时,它的作用域链如图

posted @ 2011-07-04 16:18  秋无语  阅读(708)  评论(0编辑  收藏  举报