注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

淡淡De影痕的博客

将来的你一定会感激现在拼命的自己。

 
 
 

日志

 
 
 
 

JS闭包小结  

2014-10-17 17:43:42|  分类: JS初心向小结 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
前几天看了超超,宝宝,冲冲写的闭包博客受益匪浅~在这里借鉴总结下。
一.闭包定义

在JS中正常情况下,全局变量是不能访问函数中的局部变量的。那我硬要获取怎么办呢?这个时候就要用闭包了,闭包就是能够读取其他函数内部变量的函数。

二.闭包实例

闭包实例1

function f1(){
    var n=999;
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();//调用f1函数得到返回值是一个f2函数对象,将其赋给result变量。

  result(); // 999 调用f2函数

在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的。这就是Javascript语言特有的"链式作用域"结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!
在上面这里例子中f2函数就是闭包

闭包实例2

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

var demoArr = createFunction();
for (var i = 0; i < demoArr.length; i++) {
console.log(demoArr[i]); //没有括号进行调用
};

在这个实例中运行到var demoArr = createFunction();时会调用createFunction函数,并获得一个返回的arr数组。数组中有10项,每一项中都保存着一个匿名函数function(){return i;}。当继续运行后面的for循环后,会依次遍历数组中的每一项并将其打印出来。效果如下
JS闭包小结 - 淡淡De影痕 - 淡淡De影痕的博客
 
闭包实例3

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

var demoArr = createFunction();
for (var i = 0; i < demoArr.length; i++) {
console.log(demoArr[i]()); //括号进行调用
};

本例中前面和上例相同,var demoArr = createFunction();时会调用createFunction函数,并获得一个返回的arr数组。数组中有10项,每一项中都保存着一个匿名函数function(){return i;}。咱们再来看看下面的循环,和之前不同的是这里在遍历数组时每次都会调用数组中的匿名函数。那么打印的结果是什么呢?1,2,3,4.....9?咱们看下结果~
JS闭包小结 - 淡淡De影痕 - 淡淡De影痕的博客
 打印的结果是10个10,为什么呢?咱们来分析一下~
首先,当调用createFunction函数时for循环会进行10次循环,此时arr数组中的每一项都会引用同一个保存着i值函数对象。经过10次循环后i值为10,所以数组中的引用结果也为10。由于这个例子在外部全局作用域中获取到了createFunction函数中的i值,所以形成闭包。

闭包实例4

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

};
return arr;
}

var demoArr = createFunction();
for (var i = 0; i < demoArr.length; i++) {
console.log(demoArr[i]()); // 调用了
};

再来看看这种闭包的写法~在上例中有一个比较陌生的写法(function(){})() 这个东西叫立即执行函数当程序运行到此处时,会立即执行第一个括号内的函数。这里先不说他,看看上例中是怎么一个运行过程。
首先当调用createFunction函数时同样会创建一个包涵10项的数组,咱们来详细说一说这个创建数组的过程。在for循环遍历时i值会以参数的形式传到函数中,保存到num中。之后立即执行函数会立刻将匿名函数返回出去。此时匿名函数中的num变量保存的值为以参数形式传进来的i值。由于本例中从外部作用域获取到函数内部的num参数值,故形成闭包。


JS闭包小结 - 淡淡De影痕 - 淡淡De影痕的博客

三.思考(闭包的例子已经见过不少了,它有什么缺点呢?)

var aaa = (function(){
var a = 1;
function bbb(){
a++
alert(a)
}
function ddd(){
a++
alert(a)
}
return {
b:bbb,
c:ddd
}
})()
aaa.b();
aaa.c()


四.注意

由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,只在绝对必要时候再考虑使用闭包。在IE中可能导致内存泄露。

五.IE引发内存泄露

内存泄露是指一块被分配的内存既不能使用,又不能回收,直到浏览器进程结束,使CPU不断增加。

//满足IE内存泄露的条件,一个变量获取dom节点,他的一个属性比如onclick去引用一个内部函数,而这个内部函数变量又去引用外部这个对象。这样就会存在内存泄露。
window.onload = function(){
var Odiv = document.getElementById("div");
Odiv.onclick = function(){
alert(Odiv.id)
}
}
/*解决办法*/
window.onunload = function(){
Odiv.onclick = null;
}

 欢迎大家交流指正~淡淡De影痕
  评论这张
 
阅读(240)| 评论(4)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018