從零開始學習前端JAVASCRIPT — 14、閉包與繼承
1:閉包
1 . 概念:閉包就是能夠讀取其他函數內部變量的函數。在JS中,只有函數內部的子函數才能讀取局部變量,因此可以把閉包簡單理解為”定義在一個函數內部的函數”。
2 . 閉包的特點
1)可以讀取函數內部的變量。
2)讓這些變量的值始終保存在內存中。
3 . 閉包的原理
理解閉包,首先必須理解JS變量的作用域。變量的作用域無非就是兩種(es5):全局變量和局部變量。
JS語言的特殊之處,就在於函數內部可以直接讀取全局變量。另一方面,函數外部自然無法讀取函數內的局部變量。
註意:
1)函數內部聲明變量的時候,一定要使用var聲明。如果不用的話,你實際上聲明了一個全局變量。
2)局部變量的作用域,在函數定義的時候就已經確定下來了。
出於各種原因,我們有時候需要得到函數內部的局部變量。但是正常情況下這是辦不到的。只有變通一下才能實現,那就是在函數內部再定義一個函數。外部變量不能訪問內部變量,內部變量卻能訪問外部變量,這正是因為JS特有的”鏈式作用域”結構(chain scope),子對象會一級一級地向上尋找所有父對象的變量。所以父對象的所有變量,對子對象都是可見的,反之則不成立。我們只需要把子函數返回出來,我們就可以在外部讀取內部變量了。
4 . 閉包的應用場景
1)函數作為返回值。
<!DOCTYPE html>
<html lang=" en">
<head>
<meta charset="UTF-8">
<title>閉包</title>
</head>
<body>
<script>
function f1() {
var n = 999;
nAdd = function () {
n += 1;
}
function f2() {
console.log(n)
}
return f2;
}
var result = f1();
console.log("result的第一次執行")
result();//999
console.log("nAdd的執行")
nAdd();//無輸出
console.log("result的第二次執行")
result();//1000
</script>
</body>
</html>
2)函數作為參數被傳遞。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>閉包</title>
</head>
<body>
<script>
function fun(n, o) {
console.log(o);
return {
fun: function (m) {
return fun(m, n);
}
};
}
var a = fun(0); //undefined
// 執行完並未銷毀保存在內存中
a.fun(1); //0
a.fun(2); //0
a.fun(3); //0
fun(0).fun(1).fun(2).fun(3);
//undefined、0、1、2
var a = fun(0).fun(1);
//undefined、0
a.fun(2);
//undefined、1
a.fun(3);
//undefined、1
</script>
</body>
</html>
5 . 使用閉包註意點
1)由於閉包會使得函數中的變量都被保存在內存中,內存消耗很大,所以不能濫用閉包。否則會造成網頁性能問題,在IE中可能導致內存泄漏。解決方法就是在函數退出之前,將不使用的局部變量刪除(值置為null,垃圾回收機制就會處理)。
2)閉包會在父函數外部,改變父函數內部變量的值。所以不要隨便改變父函數內部變量的值。
6 . demo通過js閉包實現鼠標滑過隔行換色的效果
2:構造函數的繼承
從零開始學習前端JAVASCRIPT — 14、閉包與繼承