闭包含义:
一般函数;
function outer() {
var localVal = 30;
return localVal
}
outer() //30
outer 函数里有一个局部变量 localVal, 值为 30. 然后 return 出去
对于一般函数, 在调用结束后, 实际上局部变量可以释放了.
具体释放要取决于垃圾回收机制
这是一般函数的情况.
但对于 javascript中的函数也是对象,
并且函数也可以作为返回值, 也可以作为传参, 函数里也可以嵌套函数.
实例如下:
function outer() {
var localVal = 30;
return function() {
return localVal
}
}
var func = outer();
func(); //30
outer函数的返回值是一个匿名函数表达式,
在匿名函数里又 return 了 outer 函数的局部变量 localVal,
所以对于一般函数的情况,函数调用返回后局部变量可以被释放.
但是这种嵌套的情况, localVal 不能被释放, 因为调用 outer 之后,
返回的是匿名函数, 匿名函数里面仍然可以访问外部 outer 的局部变量,
那么函数 outer 调用结束之后,
func 这个函数, 再次调用仍能访问到外函数的局部变量.
这种情况就是闭包.
闭包作用:
闭包的作用:
处理事件点击
处理异步请求
封装变量
等...
比如:
!function() {
var localData = "localData here";
var url = "http://www.baidu.com/";
$.ajax({
url:url,
success:function() {
//do sth.
console.log(localData)
}
})
}
success 的回调函数里用到外层的变量,
因为有闭包的缘故,
最外面匿名函数结束调用之后,
回调函数仍有能力访问到外层的 localData, url 等
封装:
闭包的小坑:
document.body.innerHTML = "<div id='div1'>aaa</div>" +
"<div id='div2'>bbb</div>" +
"<div id='div3'>ccc</div>";
for(var i = 1; i<4;i++) {
document.getElementById('div' + i);
addEventListener('click', function() {
alert(i) //all are 4!
})
}
想实现的效果是点击 aaa 的时候输出 1, 点击 bbb 输出 2, 以此类推;
但是实际上点击任何一个都返回 4.
这就是因为闭包的原因,
addEventListener 是回调函数, 当点击的时候, 这个回调函数才会动态的拿到 i 的值,
但是 i 的值在初始化完成之后已经是 4 了,
比如在 for 循环外面拿到 i 的值, 是循环最终的结果 i 是 4
如何实现真正想要的效果
改造如下:
document.body.innerHTML = "<div id='div1'>aaa</div>" +
"<div id='div2'>bbb</div>" +
"<div id='div3'>ccc</div>";
for(var i = 1; i<4;i++) {
!function(i) {
document.getElementById('div' + i);
addEventListener('click', function() {
alert(i) //all are 4!
})
}(i);
}
在每一次循环的时候, 用一个匿名函数, 而且是立即执行的匿名函数包装起来,
包装起来之后, 每一次遍历的 i 传到匿名函数里, 在匿名函数里面再用参数 i 来引用使用
这样每次点击对应的 alert 的时候, 这时的 i 都取自每次闭包环境下的 i,
这个 i 来源于每次循环的赋值时候 i