自定義函數對象的創建過程
過程的概要圖示如下:
自定義函數(/類/構造函數)對象創建過程詳細描述:
JavaScript代碼中使用關鍵詞function定義函數、或者new Function()構造器、或者調用Function()函數,來創建函數對象,其步驟如下:
1、 申請空間,分配內存。
2、 創建一個具有內置對象數據結構(build-in object data structure)的實例對象fn。
3、在實例對象fn中添加Function的內部隱式屬性或顯式屬性。
4、設置fn的內部隱式屬性[[Class]]的值爲”Function”,說明該函數對象的類名稱是”Function”。說明該函數對象是類Function的實例。
5、設置fn的內部隱式屬性[[Extensible]] 的值爲 true,說明該函數對象的屬性可以增刪。
6、設置fn的內部隱式屬性[[Prototype]]爲Function .prototype,說明該函數對象是類Function的實例。
7、設置fn的內部隱式屬性[[Call]],它是由用戶JS代碼實現的用戶方法,處理邏輯參考對象創建過程的步驟7。
8、設置fn的內部隱式屬性[[Construct]],它是由JS引擎用native code 或內置JS代碼實現的內部方法,處理邏輯參考對象創建過程的步驟1,2,3,4,5,6,7,8。
9、設置fn.length爲函數形參數量,如果函數沒有形參,則將fn.length設置爲0
10、設置函數fn.caller爲null。如果在函數執行環境下,調用函數fn,則fn.caller返回調用fn的函數對象。如果在全局執行環境下,調用函數fn,則fn.caller返回null。
11、 設置fn的內部隱式屬性[[Scope]]的靜態作用域鏈爲:
(1)用function關鍵字聲明的函數聲明語句創建的函數對象,其[[Scope]]靜態作用域鏈複製當前執行環境的執行作用域鏈。
// FunctionName可用於new,生成實例對象
function FunctionName(a){document.write(a + "<br />");}
// functionName可用於調用
function functionName(a){document.write(a + "<br />");}
(2)使用function關鍵字聲明的匿名函數表達式創建的函數對象,其[[Scope]]靜態作用域鏈複製當前執行環境的作用域鏈。
(3)使用function關鍵字聲明的命名函數表達式創建的函數對象,其[[Scope]]靜態作用域鏈複製當前執行環境的作用域鏈;在[[Scope]]靜態作用域鏈的前端添加一個Object類的實例;在該實例上添加一個屬性,名字爲函數名functionName,值爲返回的函數對象fn。
var test = function functionName(a){document.write(a + "<br />");}
(4) new Function()、Function()函數創建的函數對象的[[Scope]]靜態作用域鏈永遠複製全局執行環境的作用域鏈,只包含window對象。
var fn = new Function("形式參數1","形式參數2",...,"形式參數n","函數體");
var fn = Function("形式參數1","形式參數2",...,"形式參數n","函數體");
12、使用new Object()同樣的邏輯創建一個Object類的實例對象fnProto
13、將fnProto.constructor設爲fn。原型的顯式構造器屬性constructor引用構造函數本身,它是語法規範的一種實現。
14、將fn.prototype設爲fnProto
這部分意思是說原型的的構造方法指向實例、實例的原型指向它的原型。
15、返回fn,將fn賦值於變量對象中的changeColor。