闭包Closure

闭包指的是有权访问另一个函数作用域中变量的函数。

###函数调用过程(第一次被调用时)

1. 创建执行环境(execution context);

2. 创建作用域链,并将作用域链赋值给**特殊的内部属性Scope**;

3. 使用this和arguments等初始化函数的活动对象(activation object),外部函数的活动对象AO位于第二位,外部函数的外部函数的AO位于第三位一直排下去

作用域链本质上是一个指向变量对象的指针列表,指向各变量对象,但不包含对象。在函数中访问变量时,从作用域链中顺序查找该变量。

一般来讲,函数执行完毕之后,局部活动对象会被销毁,仅保存全局对象。

对于闭包,作用域链的销毁不同。

>

>    function a() {

>        var b = "closure";

>        return function() {

>            alert(b);

>        }

>    }

函数a内部返回的匿名函数,会将函数a的活动对象添加到自身的作用域中,因此对于该匿名函数来说,作用域链是本身-a-window。当函数a执行结束后,其活动对象不会被销毁,因为匿名函数的作用域链仍在引用这个活动对象。只有当匿名函数被销毁,函数a的活动对象才会被销毁。

作用域链的配置机制,使得闭包只能取得包含函数中任何变量的最后一个值。因为内部函数保存了外部函数的活动对象,在内部函数中引用变量时,外部函数变量的变化,内部函数中均会同时变化。

>

>    function f() {

>        var results = new Array();

>        for(var i = 0; i < 10; i ++) {

>              results[i] = function() {

>                  return i;

>              };

>        }

>        return results;

>    }

注意results中包含了10个函数,每个函数返回一个值,此时每个函数返回的都是10;因为每个内部函数均包含了函数f的活动对象,包括其中的变量i,而i对应的值最终为10;

>

>      function f() {

>          var results = new Array();

>          for(var i = 0; i < 10; i ++) {

>              results[i] = function(num) {

>                    return function() {

>                        return num;

>                    }

>              }(i);

>          }

>          return results;

>      }

js中函数传参是传值,因此通过将i值传给匿名函数,使得每次返回的值都不一样。

###闭包中的this指针

匿名函数的执行环境具有全局性,因此一般情况下this通常指向window,但也有例外。

>

>    var name = "window";

>    var obj = {

>        name : "obj",

>        f: function() {

>            return function() {

>                return this.name;

>            }

>        }

>      }

>      alert(obj.f()());//window

匿名函数的执行环境是window,因此匿名函数在调用时,作用域链是window-obj;由于第一个活动对象中已经有this指针(访问的是全局的变量name),不会再去查找作用域链,因此外部对象obj的this指针不会被访问到;而当将外部函数的this指针保存到另一个变量中时,则可以访问到,因为全局对象中没有该变量。

>

>    var name = "window";

>    var obj = {

>        name : "obj",

>        f: function() {

> var this = that;

>            return function() {

>                return that.name;

>            }

>        }

>      }

>      alert(obj.f()());//obj

你可能感兴趣的:(闭包Closure)