理解javascript闭包

之前对闭包总是一知半解,网上的大部分解释也是晦涩难懂,查了一些资料,写一些自己对闭包的理解。


闭包:作用域的艺术

要理解闭包,还是要从javascript变量作用域说起。

js变量分为局部变量和全局变量。

在 function 内部声明的是局部变量,在函数外是无法获取到局部变量的。如 

function foo1(){
    var a = 2;
}
console.log(a);//a is not defined

除非将局部变量a作为返回值调用,此时函数外部就获取到了局部变量a的值。如:

function foo1(){
    var a = 2;
    return a;
}
var data = foo1();
console.log(data);//2


举一个简单的例子来说一下闭包。假如你想统计一个页面所有按钮的点击次数。

你可以设置一个全局变量n,每点击一次运行n++,

假设这个计算过程语句再多一些,那么你可以设置一个代码块来执行,如

var n = 0;//全局变量
function add(){
    n++;
}

那么现在有个愿望,我不想要别的函数也能改变n的值,想要n的变化只与函数add有关,就是说我要把n隐藏起来,只有add能使用它。

就好像变量n只是函数add的局部变量一样。


那么就把n写成是局部变量吧。

返回n,让计数器能够知道n的值。愿望1达成,n只能由函数add调用。

function add(){
    var n = 0;//局部变量  
  n += 1;
  return n;
}

新问题又来了,

点击一次    add();//1
点击两次    add();//1
点击三次    add();//1
...

局部变量的值在函数运行完毕后就销毁了,导致每一个点击计数结果都是1.

这就蛮尴尬了呀,可是我们不能放弃,

走曲线救国的道路

var add = (function () {
    var n = 0;
    return function () {return n += 1;}
})();
点击一次    add();//1
点击两次    add();//2
点击三次    add();//3
...

OK,大功告成。


下面,解释一下运行机制。为方便描述,将匿名函数修改一下,结果如下:

var add = f1();
function f1() {
    var n = 0;    
    function f2() {return n += 1;}
    return f2;
};

首先: add 此时为一个全局变量,值为f2,即

function f2() {return n += 1;}

由于f2是定义在f1内部的函数,因此可以调用f1的局部变量n。

又因为add此时为全局变量,因此add()在运行过后 n 还存在于内存中。
需要注意的是,add()运行后 n 的变化,并不影响原f1 和 f2 中的n值。

var add = f1();
function f1() {
    var n = 0;    
    function f2() {return n += 1;}
    return f2;
};
add();//1
add();//2
add();//3

var add2 = f1();
add2();//1
add2();//2
add2();//3


总结:

我理解的闭包应该包含三个部分:

1、父函数,其中声明了不想被其他外部代码调用的局部变量;

2、子函数,可以调用父函数声明的局部变量并加以处理;

3、返回值,以子函数做为返回值赋值给全局变量,在该全局变量未被销毁的情况下,变量的运算结果将保存在内存中。

闭包的好处就是可以用一个函数来实现某个功能,减少代码的干扰,避免名称冲突,代码可复用;
缺点是内存浪费,因此不能滥用。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值