標籤:包含 module 代碼 活動 詳細介紹 date() 講解 pat argument
1.下面來個遞迴:
function factorial(num){
if(num<= 1){
return 1;
}else{
return num*factorial(num-1);
}
這是個經典的遞迴階乘函數,雖然這個函數表面上看起來沒什麼問題,但是下面代碼可能導致它出錯
var anotherFatorial =factorial;//指向函數的引用
factorial =null;
alert(anotherFatorial(4));//出錯!!!調用它會在else裡邊用到factorial如果改成arguments.callee就可以解決這個問題啦。
2.閉包的深刻理解原理(涉及到第四章的範圍鏈條,176-180頁詳細介紹為何內部的匿名函數可以訪問調用它的那個函數範圍的內容):
簡述:當a函數返回一個匿名函數b的時候,在b被a返回後,它的範圍鏈被初始化為包含a函數的使用中的物件(在每個函數被調用時,其使用中的物件都會取得this和arguments這兩個特殊變數)和全域變數對象(可以看179頁的圖)。這樣,匿名函數就可以訪問在a中定義的所有變數。更為重要的是,a函數在執行完畢後,其使用中的物件不會被銷毀,因為匿名函數b的範圍鏈仍然在引用這個使用中的物件。換句話說,就是當a函數返回後,其執行環境的範圍鏈會被銷毀,但它的使用中的物件仍然會留在記憶體中;直到匿名函數被銷毀後,a函數的使用中的物件才會被銷毀。
(**由於閉包會攜帶包含它的函數的範圍,因此會比其他函數佔用更多的記憶體。過度使用閉包可能會導致記憶體佔用過多,建議只有在絕對必要時在考慮使用閉包)
181頁:例子來深刻理解閉包
3.解釋下如下函數,它是一個函數運算式,它是個匿名函數,在多人開發中可以定義它來模仿塊範圍(通常稱為私人範圍),它的範圍被用在全域範圍之外,從而限制向全域範圍中添加過多的變數和函數,做多人開發中為了避免過多的全域變數和函數的命名衝突。而通過建立私人範圍,每個開發人員既可以有自己的變數,又不比擔心搞亂全域範圍。
(function(){
//這裡是塊級範圍
})()//這個圓括弧可以讓匿名函數立即執行
例子1:
(function(){
var now =new Date();
if(now.getMonth() == 0&&now.getDate()==1){
alert("Happy new year!");
}
})()//此段代碼放入全域範圍中,其中的變數now是匿名函數中的局部變數,我們不必在全域範圍去建立它
例子2:
function one(count){
(fucntion(){
for(var i=0;i<count;i++){
alert(i);
}
})();
alert(i);//會導致錯誤 因為在匿名函數中定義的任何變數都會在執行結束的時候銷毀,而在私人範圍中可以訪問count,是因為匿名函數是一個閉包,它能夠訪問包含範圍中的 //所有變數
}
4.js中沒有私人成員的概念,所有的對象屬性都是公有的,倒是有私人變數的概念。因此可以利用閉包來定義特權方法的方式隱藏那些不應該直接被修改的資料。187頁
5.上述缺點是必須使用建構函式模式達到了這個目的,使之缺點就是針對每個執行個體都會建立同樣一組新方法,而使用靜態私人變數來實現特權方法就可以避免這個問題。
(詳細講解靜態私人變數 188頁開始)
6.模組模式:道格拉斯所說的模組模式(module pattern)則是為單例建立私人變數和特權方法。所謂單例(singleton)指的就是只有一個執行個體的對象,按照慣例,js是以對象字面量的方式來建立單例對象的。(189頁)
JS-第七章