JavaScript核心--Function
什麽是: 保存一段可重用的代碼段的對象
何時: 只要一段代碼可能反復使用時,都要封裝為函數,反復調用函數
如何:
創建: 3種:
1. 直接量: function 函數名(參數列表){
函數體;
return 返回值;
}
缺: 會被聲明提前, 打亂程序的執行順序
解決:
2. 賦值: var 函數名=function(參數列表){
函數體;
return 返回值;
}
優: 不會被聲明提前
揭示: 函數其實也是一個引用類型的對象
函數名其實只是一個普通的變量
函數名通過地址引用函數對象
function其實是創建一個新函數對象的意思
3. 用new:
var fun=new Function("參數1","參數2",...,"函數體")
重載(overload):
什麽是: 相同函數名,不同參數列表的多個函數,在調用時,可根據傳入的參數不同,自動選擇匹配的函數執行。
為什麽: 減少API的數量,減輕調用者的負擔
何時: 只要一項任務,可能根據傳入參數的不同,執行不同的流程時。
如何:
問題
解決: arguments
匿名函數:
什麽是: 定義函數時,不指定函數名的函數
何時: 一個函數只使用一次時
為什麽: 節約內存
如何: 2種:
1. 回調函數: 定義函數後,自己不執行,交給別的函數,由別的函數控制調用和執行過程。
2. 匿名函數自調: 函數定義後,自己調用自己!
為什麽: 全局變量,用完,無法自動釋放!汙染全局!
解決: 今後禁止使用全局變量!
何時: 只有所有功能的代碼,必須放在匿名函數自調中
如何: (function(){
//函數體
})();
作用域(scope):
什麽是: 變量的可用範圍
為什麽: 保證內部的變量不會影響/幹擾外部的程序
包括: 2種:
1. 全局作用域: window
保存全局變量: 特點: 隨處可用,可重復使用!
2. 函數作用域:
保存局部變量: 特點: 僅函數內可用,不可重用!
函數的生命周期:
1. 程序開始執行前:
1. 創建執行環境棧(ECS): 用於記錄有多少函數正在被調用
2. 在ECS中記錄首先調用的瀏覽器主程序(main)
3. 創建全局作用域對象window,保存main函數執行所需的所有全局變量
2. 定義函數時:
1. 用函數名定義變量
2. 創建函數對象保存函數的定義,函數名變量通過地址引用函數對象
3. 函數對象的scope屬性,指回函數來自的作用域
3. 調用函數時:
1. 在ECS中加入本次函數調用的記錄
2. 為本次函數調用,創建函數作用域對象(活動對象AO)
3. 在活動對象AO中保存所有局部變量
4. 讓AO的parent屬性,指向函數的scope引用的作用域對象
調用過程中,變量的使用順序:
先在AO中,使用局部變量
局部沒有,才去全局找
4. 函數調用後:
1. ECS中本次函數調用的記錄,出棧
2. 導致函數作用域對象AO釋放
3. 導致AO中局部變量釋放
作用域鏈(scope chain):
什麽是: 由多級作用域對象逐級引用形成的鏈式結構
保存著所有變量
控制著變量的使用順序: 先局部,後全局
閉包
什麽是: 即重用變量,又保護變量不被汙染的一種機制
為什麽: 全局變量和局部變量都有不可兼顧的優缺點
全局: 優: 可反復使用, 缺: 隨處可用,易被汙染
局部: 優: 僅函數內可用,不會被汙染
缺: 不可重用!
何時: 今後只要希望一個變量,即可重用,又不會被汙染
如何: 3步:
1. 用外層函數包裹受保護的變量和內層函數對象
2. 外層函數將內層函數對象返回到外部
3. 使用者調用外層函數,獲得返回的內層函數
缺: 閉包比普通函數占用更多的內存空間
解決: 如果閉包不再使用,應盡快釋放!
將引用閉包結構的變量賦值為null
垃圾回收
什麽是: 引擎會自動釋放不再使用的對象的內存空間
為什麽: 內存空間大小是有限的!系統都會釋放不再被使用的對象,為後續新對象釋放更多空間。
垃圾回收器: 專門統計並回收內存中不再被使用的對象的空間的 小程序
如何:
1. 垃圾回收器伴隨主程序啟動而啟動,在後臺伴隨主程序運行而運行。
2. 垃圾回收器會記錄每個對象被幾個變量引用著
3. 只要一個對象不再被任何變量引用,則垃圾回收器自動釋放該對象
習慣: 只要一個大對象,不再被使用,應該主動將變量賦值為null
JavaScript核心--Function