什么是闭包?
闭包就是能够读取其他函数内部变量的函数。
在js中,只有函数内部的函数才能读取局部变量,所以闭包就是“定义在一个函数内部的函数”。
闭包是将函数内部和函数外部链接起来的桥梁。
闭包的应用场景
循环点击事件
<body>
<p>点我</p>
<p>点我</p>
<p>点我</p>
<p>点我</p>
<script>
function init() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) { //由于这个闭包的关系,他是循环完毕之后才返回,最终结果是4++是5
pAry[i].onclick = function() { //这个匿名函数里面根本没有i这个变量,所以匿名函数会从父级函数中去找i,
alert(i); ////当找到这个i的时候,for循环已经循环完毕了,所以最终会返回4
return arr;
}
}
}
init()
</script>
</body>
为什么会出现这种情况
那是因为 i 是全局变量 污染了其他变量 出现了变量提升。
在for循环里面的匿名函数执行 return i 语句的时候,由于匿名函数里面没有i这个变量,所以这个i他要从父级函数中寻找i,而父级函数中的i在for循环中,当找到这个i的时候,是for循环完毕的i,也就是4,所以这个box得到的是一个数组[4,4,4,4]。
这种情况不是我们想要的。
解决方法
在函数内部重新声明一下
变量 i 保存给在每个段落对象(p)上
function init() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
pAry[i].i = i;
pAry[i].onclick = function() {
alert(this.i);
}
}
}
应用闭包解决
function init3() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i<pAry.length; i++ ) {
(function(arg){
pAry[i].onclick = function() {
alert(arg);
};
})(i);//调用时参数
}
}
闭包的缺点
变量都被保存在内存中,内存消耗很大,所以不能滥用闭包。
闭包的作用
1)可以读取函数内部的变量
2)防止全局污染
闭包的特点:
a、函数嵌套函数?
b、函数内部可以引用外部的参数和变量
c、参数和变量不会被垃圾回收机制回收
有两种策略来实现垃圾回收:
标记清除 和 引用计数;
闭包的用法
创建一个匿名的函数,并立即执行它,由于外部无法引用它内部的变量,因此在函数执行完后会立刻释放资源,关键是不污染全局对象
var data= {
table : [],
tree : {}
};
(function(dm){
for(var i = 0; i < dm.table.rows; i++){
var row = dm.table.rows[i];
for(var j = 0; j < row.cells; i++){
drawCell(i, j);
}
}
})(data);
思考:为什么闭包能够访问函数内部变量
function f1(){
var n=999;
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
正常情况下f1函数是访问不到f2函数的值,但是呢,闭包在f1函数里把f2的值给返回了f1;
那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!
网友评论