两种常见的继承
-
call()借用构造函数
-
原型链继承
一、call()借用构造函数
MDN中使用的方法
在子类构造函数中使用call(),调用父类的实例成员,简单粗暴,可以给父类的构造成员传参,
但不能继承父原型。
//父类
function Suptype(name, age) {
this.name = name;
this.age = age;
this.sayHi = function () {
console.log('Hi');
}
}
Suptype.prototype.foo = 'bar';
//子类
function Subtype(name, age, capacity) {
Suptype.call(this, name, age);//借用父类构造成员
this.capacity = capacity;
};
let instance = new Subtype('peter', 21, 'student');
for (const property in instance) {
console.log(instance[property]);//返回所有能被枚举的属性值
};
//peter
//21
//function () {console.log('Hi');}
//student
//没有列出原型中的属性,说明未能继承原型
//附上call()用法
function testCall() {
this.name = 'foo';
}
let testObj = {name: "peter"};
testCall.call(testObj);//以testObj的名义来调用testCall()
//testCall()中的this就指向了testObj,修改了name
console.log(testObj.name);//foo
二、原型链继承
红宝书使用的方法
将父类实例直接赋值给子类型的原型,继承父类的一切,
但缺点是不能向父类的构造属性传参。
function Suptype() {
this.age = 18;
};
Suptype.prototype.sayHi = function () {
return 'Hi';
};
function Subtype() {
this.capacity = 'student';
};
Subtype.prototype = new Suptype();
Subtype.prototype.constructor = Subtype;//子类原型是父类实例,则子类构造器指向父类,为了保证
//实例的签名是子类,为子类原型添加一个构造器指向子
//类。
let instance = new Subtype();
console.log(student.sayHi());//Hi 能继承父类原型的属性
三、组合继承
上面两种方法都有各自的缺陷导致继承的不完整,所以可以尝试将两者结合,
在子类构造函数中使用call()继承父类的构造属性,
将父类的实例的__proto__(或者叫 [[prototype]] )赋给子类原型 。
这是一种阴间方法,__proto__并不是官方的属性。
可以吧父类实例直接赋值给子类型的原型,但父类的构造属性在实例中会出现两次,并不合适。
function Suptype(age) {
this.age = age;
};
Suptype.prototype.sayHi = function () {
return 'Hi';
};
function Subtype(age, capacity) {
Suptype.call(this,age);//call()继承
this.capacity = capacity;
};
Subtype.prototype = (new Suptype()).__proto__;//原型链继承
Subtype.prototype.constructor = Subtype;
let student = new Subtype(24,"student");
console.log(student);//age: 24, capacity: "student"
console.log(student.sayHi);//Hi
咱是小白,如果你看到觉得不对劲的地方,劳烦务必留下你的评论!谢谢!