JS闭包的详解
一、什么是闭包?
特点:
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闭包的详解的更多相关文章
- 《Node.js开发实战详解》学习笔记
<Node.js开发实战详解>学习笔记 ——持续更新中 一.NodeJS设计模式 1 . 单例模式 顾名思义,单例就是保证一个类只有一个实例,实现的方法是,先判断实例是否存在,如果存在则直 ...
- Js apply 方法 详解
Js apply方法详解 我在一开始看到JavaScript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这 ...
- ES6,ES2105核心功能一览,js新特性详解
ES6,ES2105核心功能一览,js新特性详解 过去几年 JavaScript 发生了很大的变化.ES6(ECMAScript 6.ES2105)是 JavaScript 语言的新标准,2015 年 ...
- Js apply()使用详解
Js apply方法详解 我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这 ...
- Js apply方法详解,及其apply()方法的妙用
Js apply方法详解 我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这 ...
- Vue.js 数据绑定语法详解
Vue.js 数据绑定语法详解 一.总结 一句话总结:Vue.js 的模板是基于 DOM 实现的.这意味着所有的 Vue.js 模板都是可解析的有效的 HTML,且通过一些特殊的特性做了增强.Vue ...
- JS hashMap实例详解
链接:http://www.jb51.net/article/85111.htm JS hashMap实例详解 作者:囧侠 字体:[增加 减小] 类型:转载 时间:2016-05-26我要评论 这篇文 ...
- JS - Promise使用详解--摘抄笔记
第一部分: JS - Promise使用详解1(基本概念.使用优点) 一.promises相关概念 promises 的概念是由 CommonJS 小组的成员在 Promises/A 规范中提出来的. ...
- JS变量对象详解
JS变量对象详解 开年之后工作热情一直不是很高,这几天一直处于消极怠工状态.早上不想起床,起床了不想上班.明明放假之前工作热情还一直很高,一直心心念念的想把小程序项目怼出来,结果休假回来之后画风完全不 ...
随机推荐
- 探索Redis设计与实现3:Redis内部数据结构详解——sds
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...
- linux c(一)Helloworld
终端的屏幕上输入命令如下: 使用vi helloworld.c打开helloworld.c文件,写下如下代码:
- Linux随笔 - DNS搭建
域名系统(英文:Domain Name System,缩写:DNS)是因特网的一项服务.它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网.DNS 使用TCP和UDP端口53 ...
- angular5 清除定时器
ngOnDestroy 在指令被销毁前,将会调用 ngOnDestory 方法.它主要用于执行一些清理操作,比如:移除事件监听.清除定时器.退订 Observable 等. 调用方法 1. impor ...
- Linux应急响应基础
文件排查 敏感目录文件分析 tmp目录 命令目录 /usr/bin /usr/sbin 开机启动项 /etc/init.d /etc/init.d是/etc/rc.d/init.d的软链接 文件时间 ...
- prim算法【最小生成树1】
适用范围:要求无向图 prim算法(读者可以将其读作“普里姆算法”)用来解决最小生成树问题, 其基本思想是: ·对图G(VE)设置集合S,存放已被访问的顶点, ·然后每次从集合V-S中选择与集合S的最 ...
- 100个常用js代码(转载)
作者:小萧ovo链接:https://zhuanlan.zhihu.com/p/23076321来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. JavaScript定点 ...
- linux性能查看调优
一 linux服务器性能查看1.1 cpu性能查看1.查看物理cpu个数:cat /proc/cpuinfo |grep "physical id"|sort|uniq|wc -l ...
- spark复习总结02
1.spark执行原理图 spark程序启动后创建sparkContext作为程序的入口,sparkContext可以与不同类的集群资源管理器(Cluster Manager)进行通信,从而获得程序运 ...
- Python之lambda && reduce
lambda类似于C里面的#define或者C++里面的内联函数(inline),一般都小巧精悍 >>> g=lambda x,y:x*y >>> g(3,7) 2 ...