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变量对象详解 开年之后工作热情一直不是很高,这几天一直处于消极怠工状态.早上不想起床,起床了不想上班.明明放假之前工作热情还一直很高,一直心心念念的想把小程序项目怼出来,结果休假回来之后画风完全不 ...
随机推荐
- JS基础入门篇(三十六)—面向对象( 三 )
1.class class es6 中 为 关键字用来声明 一个 类 1.只能通过new调用 2.不存在变量提升 3.多个方法之间直接书写,不需要,隔开 4.类的方法是直接定义在类的原型上的 5.定义 ...
- 開啟windows 7 ,10 的熱點功能(無線熱點)
開啟windows 7 ,10 的熱點功能: 1.首先要確定你的電腦無線芯片有無熱點功能 # netsh wlan show drivers Hosted network supported ...
- 测试技能图谱skill-map
# 测试技能图谱 ## 代码静态分析- Sonar- PMD- Infer- Android * findbugs * AndroidLint * CheckStyle- iOS * scanbuil ...
- MySQL replace 和 replace into 的用法
mysql replace实例说明: UPDATE tb1 SET f1=REPLACE(f1, 'abc', 'def'); REPLACE(str,from_str,to_str) 在字符串 st ...
- #define学习
C语言中数据有常量和变量,其中定义常量主要有两种方法,这里主要学习#define定义常量的方法. 1.#define定义数字宏常量 例子如下: 1 2 3 4 5 6 7 8 9 10 #includ ...
- Windows 08 R2_NLB负载均衡(图文详解)
目录 目录 Load Balance 使用NLB来部署Web Farm集群 环境准备 在Win08r2pc1中配置DNS服务 在Win08r2pc1中部署File Service文件服务 在Win08 ...
- 使用latex绘制多层神经网络结构图
1,使用Tikz包: 2,参考官方例程单层神经网络结构,绘制了一个含有3隐藏层的BP神经网络节点图 代码如下: \documentclass{article} \usepackage{tikz} \b ...
- Rust <7>:数据结构==>链表
enum List { Cons(u64, Box<List>), NULL, } impl List { fn new() -> List { List::NULL } fn pr ...
- Django框架(二十三)—— Django rest_framework-解析器
解析器 一.解析器的作用 根据请求头 content-type 选择对应的解析器对请求体内容进行处理,将传过来的数据解析成字典 二.使用解析器 1.局部使用 在视图类中重定义parser_classe ...
- 使用mybatis进行一对多嵌套查询时出错:输出结果:Country{id=2, name='美国', minister=[null]}
即Minister类作为Country类的关联属性. 查询的输出结果是:Country{id=2, name='美国', minister=[null]} <!--mapper.xml内容--& ...