標籤:回調 允許 賦值 存在 函數對象 變數 入參 cal 後台
什麼是: 儲存一段可重用的程式碼片段的對象
何時: 只要一段代碼可能反覆使用時,都要封裝為函數,反覆調用函數
如何:
建立: 3種:
1. 直接量: function 函數名(參數列表){
函數體;
return 傳回值;
}
缺: 會被聲明提前, 打亂程式的執行順序
解決:
2. 賦值: var 函數名=function(參數列表){
函數體;
return 傳回值;
}
優: 不會被聲明提前
揭示: 函數其實也是一個參考型別的對象
函數名其實只是一個普通的變數
函數名通過地址引用函數對象
function其實是建立一個新函數對象的意思
3. 用new:
var fun=new Function("參數1","參數2",...,"函數體")
重載(overload):
什麼是: 相同函數名,不同參數列表的多個函數,在調用時,可根據傳入的參數不同,自動選擇匹配的函數執行。
為什麼: 減少API的數量,減輕調用者的負擔
何時: 只要一項任務,可能根據傳入參數的不同,執行不同的流程時。
如何:
問題:js文法預設不支援重載,因為不允許多個同名函數同時存在!
解決: 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