es6的extends class
class Person {
constructor(gender) {
this.gender = gender;
}
say(msg) {
console.log(msg);
}
}
class Teacher extends Person {
constructor(age) {
super('male');
this.age = age;
}
}
const mike = new Teacher(26);
mike.age // 26
mike.gender // male
mike.say('hello') //hello
原型链继承
function Person(gender) {
this.gender = gender;
}
Person.prototype.say = function(msg) {
console.log(msg);
}
function Teacher(age) {
this.age = age;
}
Teacher.prototype = new Person('male');
const mike = new Teacher(26);
// mike.__proto__ === Teacher.prototype === p
// p.__proto__ === Person.prototype
mike.age // 26
mike.gender // male
mike.say('hello') //hello
- 这种方式的继承,不能动态给父类传参,一旦建立联系,就必须确认new Teacher时的入参;
- 同时由于是直接把父类实例付给子类原型,后续子类的所有实例都共享父类实例中的属性,即任何一个子类实例修改gender都会影响其他实例
构造函数继承
function Person(gender) {
this.gender = gender;
}
Person.prototype.say = function(msg) {
console.log(msg);
}
function Teacher(age) {
this.age = age;
Person.call(this, 'male')
}
const mike = new Teacher(26);
mike.age // 26
mike.gender // male
mike.say('hello') // 报错
- 父类上的属性可以绑定到子类实例上,由于是直接挂载在实例,而非实例原型上,故属性不会相互影响
- 但该方法并没有将原型链关联,即无法从子类找到父类,且子类实例无法访问父类原型链上的方法
组合继承
function Person(gender) {
this.gender = gender;
}
Person.prototype.say = function(msg) {
console.log(msg);
}
function Teacher(age) {
this.age = age;
Person.call(this, 'male');
}
Teacher.prototype = new Teacher('female');
const mike = new Teacher(26);
mike.age // 26
mike.gender // male
mike.say('hello') // hello
- 组合使用原型链继承和构造函数继承
- 可以同时继承父类属性和父类原型链上的属性
- 由于实际相当于调用了两次父类的构造函数,开销比其余方式大,同时gender属性因为会同时挂载在子类实例上,以及子类的原型上,前者会遮蔽后者,且前者在实例间不会相互影响,但后者就显得多余了
寄生继承
function Person(gender) {
this.gender = gender;
}
Person.prototype.say = function(msg) {
console.log(msg);
}
function Inherit(Parent, age) {
const obj = Object.create(new Parent('male'));
// obj.__proto__ === p
// p.__proto__ === Parent.prototype
obj.age = age;
return obj;
}
const mike = Inherit(Person, 26);
mike.age // 26
mike.gender // male
mike.say('hello') // hello
- 寄生顾名思义就是,创建一个对象实现继承,再在其上,加上各种属性
- 这种方式继承方法通常无法复用,需要更改属性的时候,就要修改方法
- 同原型链继承,该模式下,子类实例共用父类属性,会相互影响
寄生组合继承
function Person(gender) {
this.gender = gender;
}
Person.prototype.say = function(msg) {
console.log(msg);
}
function Teacher(age) {
const obj = Object.create(Person.prototype);
// obj.__proto === Person.proptype
Person.call(obj, 'male');
obj.age = age;
return obj;
}
const mike = new Teacher(26);
mike.age // 26
mike.gender // male
mike.say('hello') // hello
- 结合组合继承和寄生继承的特点,其中,直接让子类实例的原型指向父类原型,采用object.create而非new一个父类实例,避免了执行两次父类的构造方法
- 同时由于Teacher会返回一个对象,根据new的执行原理,如果构造函数返回一个对象,会以该对象作为实例后的返回
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。