闭包的理解

Posted it蛋散

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了闭包的理解相关的知识,希望对你有一定的参考价值。

  在整理笔记的时候发现,自己曾经做过一份关于闭包的笔记,觉得很有趣,当初学习的时候,满世界的去寻找答案,用百度去google一下,再用搜狐去搜狗一下,发现到头来还是要自己亲自去做测试,才能很深刻的去记住自己学过的知识,然后很无奈的否定当初自己那幼稚的做法。但不是不去查,而是在研究的时候,发现真的不懂了,才去针对闭包的某一个点去查,我喜欢有针对性的去寻找答案,而不是漫无目的。

全局变量和局部变量

言归正传,在说闭包之前,我认为,初学者必须先知道,javascript的全局变量和局部变量,并且还有他们的作用范围:

var n = 111;//全局变量
function f1(){
alert(n)   
}
f1();//111

function f1(){
var n = 123;
}
f1();
alert(n);//n is not defined

正如上面代码的结果一样:在函数外部自然无法读取函数内的局部变量,那么函数内部定义的n就不能在外部使用,所以输出的是n is not defined

但函数内部的就一定是局部变量吗?就真的不能被外部所使用吗?答案是否定的

function f2(){
var m = n = 12;
}
f2();
alert(n);//12

如上代码所显示,n能被外部所所以,此时我们能得出一个结论: 函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量(一般不推荐使用这种不用var来定义的变量)。

此时就剩下一个问题了,什么情况才算局部范围呢?

在我们学习的一般情况下,函数的{}内,相对于window来说,就是局部变量,我们也可以尝试,在一个{}里面定义变量,然后在window全局下调用,如果输出的为//n is not defined,证明{}里面的是局部变量了,为什么这样说呢?不是所有的{}里面都是局部变量吗?(当初我也这样觉得的/(ㄒoㄒ)/~~)

for(var i = 10;i<100;i++){
console.log(i);
}
alert(i);//100
if(true){
var i = 100;
}
alert(i);//100

在for循环和if判断语句的中定义的变量,在全局范围内能调用,然而,测试还没结束,接着看…..

function aa(){
for(var i = 10;i<100;i++){
console.log(i);
}
}
alert(i);//i is not defined
function aa(){ 
if(true){
var i = 100;
}
}
alert(i);//i is not defined

我们发现,原来if和for的里面所定义的变量的作用范围都是当前的作用域范围

闭包概念:

闭包概念其实有很多不同的版本,我这里用的是阮一峰的一个解释: 闭包就是能够读取其他函数内部的函数,我们先来看个例子

function f1(){
        var n = 99;
                function f2(){
                         // var a = 2;
                         alert(n);
                }
         // alert(a);//a is not defined
        f2();
}
f1();

在函数中,我们的f2函数内可以访问到f1的变量n,但f1不能访问f2里面定义的 变量a,这里就是Javascript语言特有的”链式作用域“结构,子对象会一级一级地向上找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

简单来说,儿子找老爸要资源种子,但是儿子不给老爸资源片子((????))

在了解完函数的链式作用域,我们来看看这段代码

function f1(){
// console.log(‘1’+this);
var n = 99;
nAdd = function(){//全局变量
console.log(‘nAdd的this:’+this);
n+=1;
}
function f2(){
console.log(‘f2的this:’+this);
console.log(n);
}
console.log(‘f1的this:’+this);
return f2;
}

var result = f1();//f2 赋给result;result是全局变量,则f2为全局变量,因为f2需要依赖f1才能存在(如果f1消失,则f2也会被清除,所以f1也存在内存中)
result();//99
nAdd();
result();//100

n的值从99 到100 ,证明n存在内存当中,也就是f1周期完成后,被强制留下来了,而f1的留下来, 是因为f2变成了全局变量,而f2是依赖f1才能存活,所以f1被强制留下来,所以f1内部的 局部变量也能被f2使用(也是浪费内存的原因)

闭包的优点:

  1. 缓存
  2. 实现封装,防止变量发生污染
  3. 匿名自执行函数,匿名自执行函数可以减小内存消耗

闭包的缺点:

  1. 由于闭包内部变量优先级高于外部变量,所以多查找作用域链中的一个层次,就会在一定程度上影响查找速度。
  2. 内存浪费
  3. 处理不当,容易到时内存溢出

所以关于闭包,最好就是能不用就不用,如果非用不可,那就想办法保持闭包对象的数量很少甚至唯一。

 

以上是关于闭包的理解的主要内容,如果未能解决你的问题,请参考以下文章

javascript 匿名函数及闭包----转载

python中对 函数 闭包 的理解

一段代码理解闭包

(原创)JS闭包看代码理解

理解Python中的闭包

JS闭包的概念