闭包及其作用

形成

当函数可以记住并访问所在的词法作用域时,(即使函数是在当前词法作用域之外执行的)就形成了闭包

闭包的作用域链:

  1. 自己的作用域
  2. 外部函数的作用域
  3. 全局作用域
通常函数在执行结束后其作用域和变量都会被销毁,但函数返回闭包时,函数的作用域会一直保存到闭包消失。

作用

1. 模仿块级作用域

创建并立即执行一个函数,函数中的变量会立即被销毁,除非将其赋值给了全局作用域中的变量。

2. 在对象中创建私有变量

用闭包实现公有方法,用其访问作用域中的私有变量

var fun = (function () {
        var a = 1;
        function geta() {
            return a;
        }
        Outer = function () {}
        Outer.prototype.publicMethod = function () {
            a++;
            return geta();
        }
    })();
    var o = new Outer();

    o.publicMethod();返回2

使用闭包的注意点

1.由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

实例

实现函数 makeClosures,调用之后满足如下条件:
1、返回一个函数数组 result,长度与 arr 相同
2、运行 result 中第 i 个函数,即 resulti,结果与 fn(arr[i]) 相同
输入例子:
var arr = [1, 2, 3]; var square = function (x) { return x * x; }; var funcs = makeClosures(arr, square); funcs1;

输出例子: 4

直接匿名函数
function makeClosures(arr, fn) {
    var funcs = [];
    for(var i=0; i
        (function(v){
            funcs[v] = function(){
                return fn.call(null,arr[v]);
            }
        })(i);
    }
    return funcs;
}
forEach()
function makeClosures(arr, fn) {
    var result = new Array();
    arr.forEach(function(curr){
        result.push(function(){return fn(curr)});
    })
    return result;
}
使用ES5的bind()方法
function makeClosures(arr, fn) {
    var result = new Array();
    for(var i=0;i
        result[i] = fn.bind(null,arr[i]);
    }
    return result;
}
参考《JavaScript高级程序设计》的典型方法
function makeClosures(arr, fn) {
    var result = new Array();
    for(var i=0;i
        result[i] = function(num){
            return function(){
                return fn(num);
            }
        }(arr[i]);
    }
    return result;
}

思考题

 var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      return function(){
        return this.name;
      };
    }
  };
var a = object.getNameFunc;
a()();//这里的调用者一直是window,因此输出"The Window";
object.getNameFunc()();//这里object.getNameFunc()时调用者是object,但是将object.getNameFunc()作为一个整体,他的调用者是window,是window来调用object.getNameFunc()(),此时调用者是window,因为输出"The Window";
 var name = "The Window";
  var object1 = {
    name : "My Object",
    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };
    }
  };
  object1.getNameFunc()();//这里类似上面object.getNameFunc()时调用者是object的,但是在object1.getNameFunc()的返回函数中,将this赋值给that,因此object1.getNameFunc()()中,this仍然是object,所以输出"My Object",
var e = object1.getNameFunc;
e()();//这里this一直是window,因此不管如何赋值,都输出"The Window"

下面是this的其他

var name = "The Window";
var object = {
    name : "My Object",
    getNameFunc : function(){
        return this.name;
    }
};
object.getNameFunc()
//"My Object"
(object.getNameFunc)()
//"My Object"
(object.getNameFunc = object.getNameFunc)()
//"The Window"
//最后一个object.getNameFunc的值是函数本身。function (){return this.name;}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值