1. 原型、構造函數、實例的關係
- 原型:
- 原型通過constructor指向構造函數,原型如果是自定義對象且沒有明確將constructor指向構造函數,則原型的constructor指向函數的基類Function。
- 原型通過方法isPrototypeOf檢查是否和實例之間有關係;
- 構造函數:
- 構造函數的prototype指向原型
- 因爲構造函數和原型可以生成多個實例,所以它兩者不關心其所對應的實例,沒有直接獲取其對應實例的途徑。
- 實例
- 實例的__proto__檢查指向其原型;
- 實例的constructor檢查是否和構造函數有關係
- 實例通過
Object.getPrototypeOf(實例)
可以查看其原型是誰 - 實例和原型的constructor都明確的指向構造函數,但原型如果是自定義對象且沒有明確將constructor指向構造函數,則原型的constructor指向函數的基類Function。
2. 實例化的過程
- 創建一個對象
- 創建__proto__屬性指向構造函數的prototype屬性,創建constructor屬性指向自己的構造函數;
將構造函數的所有私有屬性方法複製到自己身上;
以下爲函數實現:function Move(name) { this.name = name this.say = function() { console.log('hello,say') } } Move.prototype.age = 23; let s = new Move('tt'); console.log(s); // new關鍵字的函數實現 function newFunc(fn,...rest) { let obj = {}; obj.constructor = fn; obj.__proto__ = fn.prototype; fn.call(obj,rest); return obj; } let newS = newFunc(Move, 'tt') console.log(newS)
3. 擴展
對象兩兩不相等,因爲他們指針所對應的實際存儲位置不一致,如果一致,也是相等的。
function Move() {}
let obj = {age: 23}
Move.prototype = obj;
var m = new Move()
console.log(Move.prototype === m.__proto__) // true
console.log(Move.prototype === obj) // true
console.log(m.__proto__ === obj) // true
console.log(obj.isPrototypeOf(m)) // true
console.log(Object.getPrototypeOf(m)) // { age: 23 }