1.匿名函數
定義函數時,不使用任何變量引用的函數;
1.為何使用:使用匿名函數,可以節省內存空間,使用完畢以后立刻釋放。
2.何時使用:如果一個函數只使用一次
3.如何使用:?
? ?1>自調: ? 創建完函數立刻執行
(function (){console.log("aaa")})()? ? ? ? // aaa
(function(date){console.log(date.toGMTString())})(new Date())?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //Wed, 15 Mar 2017 07:13:44 GMT
? ?2>回調: ? 將函數傳給另一個函數使用
arr.sort(function(a,b){return a-b});?
2.函數重載
js中實際上不存在重載的概念,因為js中不支持同時包含多個同名函數,最后定義的同名函數會覆蓋之前定義的。但一個函數可以通過不同的參數列表(類數組對象arguments)來實現各個功能,我們稱之為函數重載。
傳統方式1;
var overrideMethods = function(){
? ? switch (arguments.length){
? ? ? ? case 0 :
? ? ? ? ? ? ? ? console.log("class no body");
? ? ? ? ? ? ? ? break;
? ? ? ? case 1:
? ? ? ? ? ? ? ? console.log("class has one body");
? ? ? ? ? ? ? ? break;
? ? ? ? case 2:
? ? ? ? ? ? ? ? console.log("class has two body");
? ? ? ? ? ? ? ? break;
? ? ? ? }
}
overrideMethods();? //class no body
overrideMethods("wu");? //class one body
overrideMethods("wu","li");? //class two body
3垃圾回收
清除不再使用的對象,釋放存儲空間。
垃圾回收進程器:是一個專門負責釋放不再使用的對象的小程序。js引擎自帶,自動執行,后臺程序。
垃圾回收的原理:(對象的生命周期)
1.創建一個對象時,垃圾回收器會標記該對象的引用計數器為1;
2.使用對象的過程中,只要多一個變量引用該對象,計數器就+1;
3.主動為一個變量賦值為null時,就釋放了該變量對對象的引用。計數器就-1;
4.如果一個對象不在被任何變量引用,計數器就變為0.垃圾回收就釋放對象。
在使用完一個較大的對象后,都要主動用null釋放對該對象的引用。
4.函數的生命周期
1.當程序開始執行時:創建一個 Execution ?Context Stack(ECS 執行環境棧),創建全局作用域對象 ,在ECS中壓入第一個全局執行環境EC,全局EC引用window;
2.當定義函數時:(就是定義函數對象,封裝函數定義)在函數對象中,設置scope屬性,引用函數來自的作用域,通常scope都是window
3.創建一個活動的對象Actived Object(AO),向ECS中壓入本次函數調用的執行環境EC,EC的scope chain引用AO。
4.當函數調用結束后,EC出棧,導致AO無EC引用,被釋放。
1.ECS(執行環境棧):保存正在調用的函數的執行環境的棧結構
2.AO(活動對象):保存函數的局部變量的函數作用域對象。
結論:
1.單線程
2.同步執行,只有棧頂的上下文處于執行中,其他的上下文需要等待
3.全局上下文只有唯一的一個,他在瀏覽器關閉的時候出棧
4.執行上下文的個數沒有限制
5.每次某個函數被調用,就會有新的執行上下文為其創建,即使調用的自身函數,也是如此。
5.作用域和作用域鏈
作用域:一個變量的使用范圍
window是全局作用域,AO對象是函數作用域,AO對象引用著window對象
作用域鏈:由各級作用域對象,逐級引用形成的鏈式結構,就是作用域鏈,作用域鏈的末尾是window對象。
作用域鏈控制著變量的使用順序:
1.優先使用AO中的局部變量;
2.如果AO中沒有,就延作用域鏈向下找
3.如果到window對象仍然沒找到,就報錯。
6.閉包
重用變量,保護變量不受污染的機制。
如何使用:
1.用外層函數將受保護的變量和操作變量的函數封裝在內部。
2.外層函數將內層函數返回
3.調用外層函數,獲得返回的內層函數對象。
function f1(){
? ? var n = 999;
? ? function f2(){
? ? ? ? alert(n); ? ? ?//內層函數操作受保護的變量
? ? }
? ? return f2;
}
var result = f1(); ? ? //result ?為 ?f2()
result(); ? //999
函數執行時,首先創建一個ECS,全局作用域入棧,遇到可執行代碼 ? var result = f1();
f1()的EC入棧,執行結束以后 return f2;并賦值給result,此時變量result 指向f2();f1()執行結束出棧,繼續執行代碼,result()的EC入棧,執行代碼,結束后出棧。
注意:函數中,遇到return 能直接終止可執行代碼的執行,因此會直接將當前EC彈出。