JavaScript学习之路09_闭包

**

闭包

**
函数作为返回值

function sum(arr){
    return arr.reduce(function(x,y){ 
        return x+y;
    });
};
sum([1,2,3,4,5]);
15

如果不需要立刻求和,而是在后面的代码中,根据需要再计算怎么办?可以不返回求和的结果,而是返回求和的函数!

function lazy_sum(arr) {
    var sum = function () {
        return arr.reduce(function (x, y) {
            return x + y;
        });
    }
    return sum;
}
var f = lazy_sum([1, 2, 3, 4, 5]); 
//在调用f的时候才真正的计算求和的结果
f(); //15

什么时候闭包?
在函数lazy_sum中又定义了函数sum,并且,内部函数sum可以引用外部函数lazy_sum的参数和局部变量,当lazy_sum返回函数sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包”。

//当我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数:
var f1 = lazy_sum([1, 2, 3, 4, 5]);
var f2 = lazy_sum([1, 2, 3, 4, 5]);
f1 === f2; //false

//我刚才的那个和这个是不一样的
function count(){
    var arr = []; 
    for(var i=0; i<3; i++){
        arr.push(function(){
        return i*i; 
        }); 
    } 
    return arr;
};
var results = count();
//本应该结果是0,1,4
var f1 = results[0]; //9
var f2 = results[1];//9
var f3 = results[2];//9
为什么呢?
原因就在于返回的函数引用了变量i,但它并非立刻执行。
解决办法:
再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变:
function count(){
    var arr = []; 
    for(var i=1; i<=3; i++){ 
        arr.push((function(n){
        return function(){
            return n*n;
        }})(i));
    }
    return arr;
};
var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
f1();
1
f2();
4
f3();
9
//匿名函数
(function(n){
    return n*n;
}(3));
//9
闭包还可以减少参数
function make_pow(n){
    return function(x){
        return Math.pow(x, n); 
}};
//先给make_pow()赋值
var pow2 = make_pow(5);
//然后在给内部函数赋值,减少了一个参数
pow2(2);
32

function foo(x) {
    var tmp = 3;
    function bar(y) {
        alert(x + y + (++tmp));
    }
    bar(10);
}
foo(2)

案例:
//这样不算输出几次,值都是15
function foo(x){
    var tmp = 3; 
    function bar(y){
        alert(x+y+tmp);
    }; 
    bar(10);
};
foo(2);

//但是这样的话就是每调用一次,值都会增加一
function create_counter(initial){
    var x = initial || 0; 
    return {
    inc:function(){
        x += 1; 
        return x;
        }
    }
}
var c1 = create_counter(10);
c1.inc();
11
c1.inc();
12

案例

//定义一个全局变量
var a = 100;
function f1(){
    //在函数内部可以调用全局变量
    alert(a); 
}
f1(); //100

function f1(){
    var n=999; 
    function f2(){
        alert(n); 
    } 
    return f2;
};
var result = f1();
result();//999
result();//1000

function f1(){
    var n=999;
    nAdd=function(){
        n+=1
    }
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999
   nAdd();
  result(); // 1000
   nAdd();
  result(); // 1001

练习

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

总结:
由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成”定义在一个函数内部的函数”。
所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
闭包的特点:
1.作为一个函数变量的一个引用,当函数返回时,其处于激活状态。
2.一个闭包就是当一个函数返回时,一个没有释放资源的栈区。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值