基礎閉包
閉包
1、什么是閉包
fn套fn,內部fn可引用外部fn的參數和變量
內部被引用的參數和變量,不會被JS垃圾回收機制收回
2、閉包有什麼好處,哪方面應用
1).希望一個變量長期在內在中
2).避免全局變量污染
a.模塊化代碼
b.在循環中找到對應元素的索引
3).私有成員存在
3、閉包注意的地方
IE下可能引發內存洩漏
最簡單例子首先:
function aaa() {
var a = 1;
}
aaa() //执行完后即会被垃圾回收机制收回*/
fn套fn,內部fn可引用外部fn的參數和變量
function aaa() {
var a = 5;
function bbb() {
alert(a)
}
return bbb;
}
var c = aaa(); //这里aaa()已经执行完
c(); //c(),表示bbb函数*/
再一個:a能累加,但必須是全局變量
var a = 1;
function aaa() {
a++;
alert(a)
}
aaa(); //2
aaa(); //3
alert(a) //a是全局,所以能调用到,下面需要变成局布变量;
內部被引用的參數和變量,不會被JS垃圾回收機制收回
問題:如何使a在執行過程中有效,比如a++能累加,並且a又是一個局部變量?
//當a是局部變量時,不會累加了
function aaa() {
var a = 1;
a++;
alert(a);
}
aaa(); //2
aaa(); //2 ,调用重新生成,不会累加,下面 既让a是局布变量,又可以累加*/
function aaa() {
var a = 1; //相对于内部可被找到,又不受外部执行函数影响
return function () { //函数嵌套函数
a++;
alert(a)
}
}
var b = aaa()
b(); //2
b(); //3 即时局布变量又能累加
alert(a) //a is not defined,说明a是局部变量*/
問題:如何把以上函數聲明改寫為函數表達式?
//常識:
function aaa() {
alert(1)
}
aaa()
//該寫為函數表達式:
(function () { //可以把aaa去掉
alert(1)
}) ();
所以問題的答案是:
a.模塊化代碼
var aaa = (function () { //aaa是函数执行完后的返回值
var a = 1;
return function () {
a++
alert(a)
}
}) ()
aaa(); //2 aaa(),执行的即是return 后的函数
aaa(); //3 a在外面调用不到,又能累加,模块化代码;
問題:定義函數的私有方法?
var aaa = (function () {
var a = 1; //a是局部变量,bbb,ccc是它的私有方法 在aaa函数外面调用不到
function bbb() {
a++;
alert(a)
}
function ccc() {
a++;
alert(a)
}
return { //特別留意:定義形式
b: bbb,
c: ccc
}
}) ()
aaa.b() //2 調用
aaa.c() //3 調用
alert(a) //not defined
alert(bbb) //not defined
alert(ccc) //not defined
b.在循環中找到對應元素的索引
<ul>
<li>第0個li</li>
<li>第1個li</li>
<li>第2個li</li>
</ul>
var li = document.getElementsByTagName('li')
for (var i = 0; i < li.length; i++) {
li[i].onclick = function () {
alert(i) //都是3 ,循环执行结束时i=3,alert还未执行,当去点击时才会执行
}
}
解決一:循環中i當參數傳進來
for (var i = 0; i < li.length; i++) {
(function (i) { //1、先写匿名函数,当去执行时把i传进来
li[i].onclick = function () { //2、内部函数可以调用外部函数传进来的参数;
alert(i)
}
}) (i)
}
解決二:寫return返回
for (var i = 0; i < li.length; i++) {
li[i].onclick = (function (i) { //1、当点击时,3、执行完时 5、然后把i传进来
return function () { //4、写return返回值
alert(i)
}
}) (i) //2、先执行一次 5、把i传进去
} //7、因循环时,执行完毕后i已经存在内存中的i,调用时不是外面的i,所以能弹出0,1,2
iE下可能引发内存泄漏
問題描述:当一个变量box由dom获取或数组对象获取时,它的属性如onclick去引用一个内部fn,内部函数的对像box是去引用外面的,即会引发内部泄漏,IE下首尾互相引用时
解決:onunload後把對像變為null; 提前在外面引用,之後對象置null
var box = document.getElementById('box')
box.onclick = function () {
alert(box.id)
}
解決一:
window.onunload = function () {
box.onclick = null; //onunload后把box变为null即可
}
解决二:提前在外面引用,比如 var id = box.id,里面调用alert(id),之后對象置null;
var id = box.id
box.onclick = function () {
alert(id)
}
box = null;