闭包与变量

作用域链的这种配置机制引出了一个值得注意的副作用,即闭包只能取得包含函数中任何变量的最后一个值。闭包所保存的是整个变量对象,而不是某个特殊的变量。

function createFunctions() {
       var result = new Array();
       for(var i = 0; i<10; i++){
           result[i] = function () {
               return i;
           };
       }
       return result;
   }

上述函数会返回一个函数数组。表面上看,似乎每个函数都应该返回自己的索引值,即位置0返回0,但实际上每个函数都会返回10。因为每个函数的作用域链中都保存着createFunctions()函数的活动对象,所以他们引用的都是同一个变量i。但是我们可以创建另一个匿名函数强制让闭包的行为符合预期。

function createFunctions() {
       var result = new Array();
       for(var i = 0; i<10; i++){
           result[i] = function (num) {
               return function () {
                   return num;
               };
           }(i);
       }
       return result;
   }

在上述例子中,我们并没有直接将闭包赋值给数组,而是定义了一个匿名函数,并将立即执行该匿名函数的结果赋值给数组。在这里匿名函数有一个参数num,也就是最终函数要返回的值。在调用每个匿名函数时,我们传入了变量i。由于函数参数是按值传递的,所以就会将变量i的当前值赋值给参数num。而在这个匿名函数内部,又创建并返回了一个访问num的闭包。因此,result数组中的每个函数都有自己num变量的一个副本,因此可返回不同的值。

this对象

众所周知,this对象是在运行时基于函数的执行函数绑定的:在全局函数中,this等于window,而当函数被作为某个对象调用时,this等于那个对象。不过,因为匿名函数的执行环境具有全局性,因此this对象通常指向window。

   var name = "The Window";
   var object = {
       name: "My Object",
       getNameFunc: function () {
           return function () {
               return this.name;
           };
       }
   };
   alert(object.getNameFunc()()); //"The Window"
   var name = "The Window";
   var object = {
       name: "My Object",
       getNameFunc: function () {
           var that = this;
           return function () {
               return that.name;
           };
       }
   };
   alert(object.getNameFunc()()); //"My Object"

在定义匿名函数之前,我们把this对象赋值给了一个名叫that的变量。而定义了闭包之后,闭包也可以访问这个变量,因为它是我们在包含函数中特意声明的一个变量。即使在函数返回之后,that也仍然引用着object。

你可能感兴趣的:(前端)