1:閉包 1>概念:閉包就是能夠讀取其他函數內部變數的函數。在JS中,只有函數內部的子函數才能讀取局部變數,因此可以把閉包簡單理解為”定義在一個函數內部的函數”。 2>閉包的特點 1)可以讀取函數內部的變數。 2)讓這些變數的值始終保存在記憶體中。 3>閉包的原理 理解閉包,首先必須理解JS變數的作用 ...
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:構造函數的繼承
所謂"構造函數",其實就是一個普通函數,但是內部使用了this變數。對構造函數使用new 運算符,就能生成實例,並且this變數會綁定在實例對象上。
詳解new的執行過程:
1:在記憶體生成一個實例對象obj。
2:指定實例對象的__proto__到構造函數的prototype。
3:運行構造函數,相當於運行fn.call(obj)。
4:檢查返回值,如果返回值為基本數據類型,則無視該返回值,而將生成的對象返回。如果為引用類型,則將該返回值返回。
構造函數很好用,但是存在浪費記憶體的問題。
JS規定,每一個構造函數都有一個prototype屬性,指向另一個對象。這個對象的所有屬性和方法,都會被構造函數的實例繼承。
- instanceof運算符:判斷對象是不是構造函數的實例,是則true,否則false。
- isPrototypeOf:判斷prototype對象和某個實例之間的關係。
- hasOwnProperty:每個實例對象都有一個hasOwnProperty方法,用來判斷某一個屬性到底是本地屬性,還是繼承自prototype對象的屬性。
- in運算符:in運算符可以用來判斷,某個實例是否含有某個屬性,不管是不是本地屬性。