一、什么是闭包?

特点:

1 函数嵌套函数

2 内部函数可以引用外部的参数和变量

3 参数和变量不会被垃圾回收机制所回收

举一个简单的闭包的例子,例子中符合闭包的三个特点

function aaa(a){
var b = 5;
function bbb(){
alert(a);
alert(b);
}
}
aaa();

关于js 中的垃圾回收机制,这里说明一下。请看下面代码,当aaa函数执行完毕之后,aaa中的变量a会被js的垃圾回收机制所回收

function aaa(){
var a = 1;
}
aaa(); // 改函数执行完毕时候,函数中的变量a会被js的垃圾回收机制所回收

再举一个闭包例子

当aaa函数执行完毕之后,调用c函数仍然可以弹出1,说明了a这个变量没有被垃圾回收

function aaa(){
var a = 1;
function bbb(){
alert(a);
}
return bbb;
}
var c = aaa(); // 当aaa函数执行完毕之后,调用c函数仍然可以弹出1,说明了a这个变量没有被垃圾回收
c();

二、闭包有什么好处?应用在哪?

2.1 好处:

1 可以使一个变量常驻内存

2 避免全局变量的污染

3 私有成员变量的存在

举个例子,例子中,使用全局变量a实现每次调用aaa函数,变量a++,过多使用全局变量不容易维护(全局变量的污染)。

var a = 1;
function aaa(){
a++;
alert(a);
}
aaa(); //2
aaa(); //3
alert(a); // 这里的a是全局变量

下面,使用闭包实现这个例子:

由于a是局部变量,防止了全局变量污染

function aaa(){
var a = 1;
return function bbb(){
a++;
alert(a);
}
}
var b = aaa();
b(); //2
b(); //3
alert(a); // 由于a是局部变量,外面无法引用,程序报错

使用函数表达式的形式,改造上面例子

关于函数表达式的知识点,可以查看JS函数声明与函数表达式的区别 http://www.cnblogs.com/linhp/p/6085567.html

var aaa = (function (){
var a = 1;
return function bbb(){
a++;
alert(a);
}
})();// 这里已经执行了
aaa(); //2
aaa(); //3

私有成员变量的例子:

将表达式中的函数bbb与ccc通过json的方式返回,外部只能调用返回的json中的函数bbb和ccc,而无法访问a这个成员变量。

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

2.2 用法:

1 模块化代码

2 在循环中,直接找到对应元素的索引

模块化代码就不举例了,上面的代码都能体现

下面举例(在循环中,直接找到对应元素的索引)

先看下面例子:

<script>
window.onload = function (){
var oLi = document.getElementsByTagName("li");
for (var i = 0; i < oLi.length; i++) {
oLi[i].onclick = function (){
alert(i);
}
}
}
</script>
<ul>
<li>111111111111</li>
<li>222222222222</li>
<li>333333333333</li>
</ul>

上面例子中,想通过给每一个li添加点击事件,点击每个li,弹出li的索引,而上面例子中,由于for循环已经结束,而onclick事件还没触发,此时i已经等于3了,所以你无论点击哪一个li都无法获取索引,弹出的值都是3

下面,通过闭包的形式,改造,获取索引

window.onload = function (){
var oLi = document.getElementsByTagName("li");
for (var i = 0; i < oLi.length; i++) {
(function(i){
oLi[i].onclick = function (){
alert(i);
}
})(i); //循环过程中,这里已经执行了。参数i永驻内存,所以当你点击li的时候,可以获取得到0,1,2
}
}

也可以改造成下面的样子

window.onload = function (){
var oLi = document.getElementsByTagName("li");
for (var i = 0; i < oLi.length; i++) {
oLi[i].onclick = (function (i){
return function(){
alert(i)
};
})(i);
}
}

三、闭包需要注意的地方?

3.1 IE下会引发内存泄露

内存泄露会导致浏览器内存占用过高,内存中的变量无法变量,必须关闭浏览器,关闭这个网页也无法清除

window.onload = function(){
var oDiv = document.getElementById("div1");
oDiv.onclick = function(){
alert(oDiv.id); // 由于内部引用了oDiv,导致oDiv无法释放
}
}

可以通过onunload事件,将onclick取消,来释放oDiv

window.onload = function(){
var oDiv = document.getElementById("div1");
oDiv.onclick = function(){
alert(oDiv.id); // 由于内部引用了oDiv,导致oDiv无法释放
} window.onunload = function(){
oDiv.onclick = null;
}
}

或者:

window.onload = function(){
var oDiv = document.getElementById("div1");
var id = oDiv.id;
oDiv.onclick = function(){
alert(id); // 由于内部引用了oDiv,导致oDiv无法释放
}
oDiv = null;
}

JS闭包的详解的更多相关文章

  1. 《Node.js开发实战详解》学习笔记

    <Node.js开发实战详解>学习笔记 ——持续更新中 一.NodeJS设计模式 1 . 单例模式 顾名思义,单例就是保证一个类只有一个实例,实现的方法是,先判断实例是否存在,如果存在则直 ...

  2. Js apply 方法 详解

    Js apply方法详解 我在一开始看到JavaScript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这 ...

  3. ES6,ES2105核心功能一览,js新特性详解

    ES6,ES2105核心功能一览,js新特性详解 过去几年 JavaScript 发生了很大的变化.ES6(ECMAScript 6.ES2105)是 JavaScript 语言的新标准,2015 年 ...

  4. Js apply()使用详解

    Js apply方法详解 我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这 ...

  5. Js apply方法详解,及其apply()方法的妙用

    Js apply方法详解 我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这 ...

  6. Vue.js 数据绑定语法详解

    Vue.js 数据绑定语法详解 一.总结 一句话总结:Vue.js 的模板是基于 DOM 实现的.这意味着所有的 Vue.js 模板都是可解析的有效的 HTML,且通过一些特殊的特性做了增强.Vue ...

  7. JS hashMap实例详解

    链接:http://www.jb51.net/article/85111.htm JS hashMap实例详解 作者:囧侠 字体:[增加 减小] 类型:转载 时间:2016-05-26我要评论 这篇文 ...

  8. JS - Promise使用详解--摘抄笔记

    第一部分: JS - Promise使用详解1(基本概念.使用优点) 一.promises相关概念 promises 的概念是由 CommonJS 小组的成员在 Promises/A 规范中提出来的. ...

  9. JS变量对象详解

    JS变量对象详解 开年之后工作热情一直不是很高,这几天一直处于消极怠工状态.早上不想起床,起床了不想上班.明明放假之前工作热情还一直很高,一直心心念念的想把小程序项目怼出来,结果休假回来之后画风完全不 ...

随机推荐

  1. SCP-bzoj-1079

    项目编号:bzoj-1079 项目等级:Safe 项目描述: 戳这里 特殊收容措施: DP.普通的状压状态数515,显然TLE+MLE,我们考虑把底数和幂换一换,压成155的状态数. 故状态设计为:f ...

  2. python 的按位与、或、异或 运算

    符号 描述 运算规则                        by MoreWindows & 与 两个位都为1时,结果才为1     (统计奇数) | 或 两个位都为0时,结果才为0  ...

  3. MSSQLSERVER错误1

      错误信息 数据库日志记录 09/07/2017 16:10:31,登录,未知,Login failed for user 'NT AUTHORITY\SYSTEM'. 原因: 无法打开明确指定的数 ...

  4. 分布式系统理论基础6:Raft、Zab

    本文转自:https://www.cnblogs.com/bangerlee/p/5991417.html 本文转自 https://www.cnblogs.com/bangerlee/p/52684 ...

  5. Android获取手机和系统版本等信息的代码

    有时候需要统计手机的型号和版本号,利用程序可以获取到相应的手机信息,对比两部手机发现,厂商不同,某个信息显示方式也不尽相同,具体见: String phoneInfo = "Product: ...

  6. leetcode上的一些单链表

    147- 思路: 148- 思路: 24- 思路: 25- 思路: 21- 思路: 109- 思路: 237- 思路:

  7. linux 安装memcache

    cd /usr/local/src  #进入软件包存放目录wget http://pecl.php.net/get/memcache-2.2.6.tgz  #下载tar zxvf memcache-2 ...

  8. java对象属性为date oracle数据库字段为Timestamp 处理方式

    解决方案 SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); java.util.Date da ...

  9. LeetCode刷题笔记-递归-反转二叉树

    题目描述: 翻转一棵二叉树. 解题思路: 1.对于二叉树,立马递归 2.先处理 根节点,不需改动 3.处根的左子树和右子树需要交换位置 4.递归处理左子树和右子树.步骤见1-3步 Java代码实现: ...

  10. prim算法【最小生成树1】

    适用范围:要求无向图 prim算法(读者可以将其读作“普里姆算法”)用来解决最小生成树问题, 其基本思想是: ·对图G(VE)设置集合S,存放已被访问的顶点, ·然后每次从集合V-S中选择与集合S的最 ...