《JavaScript設計模式與開發實踐》——JavaScript中使用new關鍵字建立物件例項
阿新 • • 發佈:2019-02-19
首先
- JS中的物件都具有__proto__屬性
- Function是特殊的物件,除了擁有__proto__屬性,還有特有的屬性——原型屬性(prototype),這個屬性是一個指標,指向一個物件,而這個物件的用途包含可以由特定型別的所有例項共享的屬性和方法
舉個例子:
function Person( name ){ this.name = name; }; Person.prototype.getName = function(){ return this.name; }; var p1 = new Person('Amy'); console.log(p1.name); // 輸出:"Amy" console.log(p1.getName()); // 輸出:"Amy" console.log( Object.getPrototypeOf( p1 ) === Person.prototype ); // 輸出: true
由以上例子可以看出:
- 例項 p1 可以訪問到建構函式 Person 裡的屬性
- 例項 p1 訪問到 Person.prototype 中的屬性
下圖為物件之間的關係:
模擬new關鍵字建立物件(這段程式碼來自《JavaScript設計模式與開發實踐》):
var objectFactory = function() { var obj = new Object(); /** 從 Object.prototype 上克隆一個空的物件 **/ var Constructor = [].shift.call(arguments); /** 取得外部傳入的構造器,本例中為 Person **/ /** 讓 obj.__proto__ 指向 Person.prototype, 取代原來的 Object.prototype **/ obj.__proto__ = Constructor.prototype; var ret = Constructor.apply(obj, arguments); /** 借用外部傳入的構造器給 obj 設定屬性 **/ return typeof ret === 'object' ? ret : obj; /** 確保構造器總是會返回一個物件 **/ }; var a = objectFactory( Person, 'Alex' ); console.log( a.name ); // 輸出: Alex console.log( a.getName() ); // 輸出: Alex console.log( Object.getPrototypeOf( a ) === Person.prototype ); // 輸出: true
- 用new Object() 的方式新建了一個物件 obj (此時obj原型指向Object.prototype);
- 取出第一個引數,就是我們要傳入的建構函式(本例中為 Person)。此外因為 shift會修改原陣列,所以 arguments 會被去除第一個引數;
- 將 obj 的原型指向建構函式(Person.prototype),這樣 obj就可以訪問到建構函式原型中的屬性;
- 使用 apply,改變建構函式 this 的指向到新建的物件(這樣 obj就可以訪問到建構函式中的屬性),給 obj 設定屬性;
- 返回 obj,並確保構造器總是會返回一個物件