Object.create()實(shí)現(xiàn)經(jīng)典繼承
const person = {
isHuman: false,
printIntroduction: function () {
console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
}
};
const me = Object.create(person);
me.name = "Matthew"; // "name" is a property set on "me", but not on "person"
me.isHuman = true; // inherited properties can be overwritten
me.printIntroduction();
// expected output: "My name is Matthew. Am I human? true"
Object.prototype.toString.call(me) // "[object Object]"
me和person都是Object對象拷沸,me繼承了person的所有屬性。
看看Object.create()的Polyfill
if (typeof Object.create !== "function") {
Object.create = function (proto, propertiesObject) {
if (typeof proto !== 'object' && typeof proto !== 'function') {
throw new TypeError('Object prototype may only be an Object: ' + proto);
} else if (proto === null) {
throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument.");
}
if (typeof propertiesObject != 'undefined') {
throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument.");
}
function F() {}
F.prototype = proto;
return new F();
};
}
Object.create()返回一個新的對象,這個對象的prototype
指向proto
。
ES5
function Person(name) {
this.name = name
}
Person.prototype.sayHello = function() {
console.log(this.name + ' say: hello')
}
function Teacher(subject) {
Person.call(this)
this.subject = this.subject
}
console.log(Teacher.prototype.constructor) // [Function: Teacher]
console.log(Teacher.prototype instanceof Person) // false
Teacher.prototype = Object.create(Person.prototype)
console.log(Teacher.prototype instanceof Person) // true
console.log(Teacher.prototype.constructor) // [Function: Person]
Teacher.prototype.constructor = Teacher
將父類原型指向子類
function inheritPrototype(subType, superType){
var prototype = Object.create(superType.prototype); // 創(chuàng)建對象再层,創(chuàng)建父類原型的一個副本
prototype.constructor = subType; // 增強(qiáng)對象,彌補(bǔ)因重寫原型而失去的默認(rèn)的constructor 屬性
subType.prototype = prototype; // 指定對象堡纬,將新創(chuàng)建的對象賦值給子類的原型
}
ES6類繼承extends
extends
關(guān)鍵字主要用于類聲明或者類表達(dá)式中聂受,以創(chuàng)建一個類,該類是另一個類的子類烤镐。其中constructor
表示構(gòu)造函數(shù)蛋济,一個類中只能有一個構(gòu)造函數(shù),有多個會報(bào)出SyntaxError錯誤,如果沒有顯式指定構(gòu)造方法职车,則會添加默認(rèn)的 constructor
方法瘫俊,使用例子如下。
class Rectangle {
// constructor
constructor(height, width) {
this.height = height;
this.width = width;
}
// Getter
get area() {
return this.calcArea()
}
// Method
calcArea() {
return this.height * this.width;
}
}
const rectangle = new Rectangle(10, 20);
console.log(rectangle.area);
// 輸出 200
-----------------------------------------------------------------
// 繼承
class Square extends Rectangle {
constructor(length) {
super(length, length);
// 如果子類中存在構(gòu)造函數(shù)悴灵,則需要在使用“this”之前首先調(diào)用 super()扛芽。
this.name = 'Square';
}
get area() {
return this.height * this.width;
}
}
const square = new Square(10);
console.log(square.area);
// 輸出 100
extends
繼承的核心代碼如下,其實(shí)現(xiàn)和上述的inheritPrototype
方式一樣
function _inherits(subType, superType) {
// 創(chuàng)建對象积瞒,創(chuàng)建父類原型的一個副本
// 增強(qiáng)對象川尖,彌補(bǔ)因重寫原型而失去的默認(rèn)的constructor 屬性
// 指定對象,將新創(chuàng)建的對象賦值給子類的原型
subType.prototype = Object.create(superType && superType.prototype, {
constructor: {
value: subType,
enumerable: false,
writable: true,
configurable: true
}
});
if (superType) {
Object.setPrototypeOf
? Object.setPrototypeOf(subType, superType)
: subType.__proto__ = superType;
}
}