Class Extends类继承
/* ES6 类继承 */class Person{constructor(name,age){this.name=name;this.age=age;}introduce(){console.log(name,age)}}class Student extends Person{constructor(id,name,age){super(name,age);this.id=id;}}const stu=new Student(1,'rv',20);stu.introduce() // 'rv' 20
类继承原理实现
- 原型链继承
- 构造函数继承
- 组合继承
- 寄生组合继承
原型链继承
将父类的实例作为子类的原型
/* Person */function Person(name,age){this.name=name;this.age=age;}Person.prototype.introduction=function(){console.log(name,age)}/* Student */function Student(id,name,age){this.id=id;}// 原型链继承Student.prototype=new Person('rv',20);Student.prototype.constuctor=Student;/* 测试 */const stu1=new Student(1,'rv',20);const stu2=new Student(2,'cw',10);// 缺陷1:实例化子类时,无法向父类传参,仅能通过修改原型链继承的Person实例传参console.log(stu1) // {id: 1}console.log(stu2) // {id: 2}stu1.introduce() // 'rv' 20stu2.introduce() // 'rv' 20// 缺陷2:引用值共享:由于共用相同Person实例作为原型,原型内父类的属性共享stu1.__proto__.name='foo';console.log(stu2.name) // 'foo'
构造函数继承
在子类构造函数内部通过
apply()、call()、bind()调用父类构造函数,从而将父类构造函数绑定在子类上
/* Person */function Person(name,age){this.name=name;this.age=age;}Person.prototype.introduction=function(){console.log(name,age)}/* Student */function Student(id,name,age){this.id=id;// 构造函数继承Person.call(this,name,age);// 或者Person.apply(this,[name,age]);}/* 测试 */const stu1=new Student(1,'rv',20);const stu2=new Student(2,'cw',10);console.log(stu1) // {id:1, name:'rv', age:20}console.log(stu2) // {id:2, name:'cw', age:10}// 缺陷1:无法获取到原型上的方法stu1.introduce() // undefinedstu2.introduce() // undefined
组合继承
由于原型链继承实现了原型方法却缺少自身属性,而构造函数继承实现了自身属性却缺少原型方法,将其组合可互补缺陷
/* Person */function Person(name,age){this.name=name;this.age=age;}Person.prototype.introduction=function(){console.log(name,age)}/* Student */function Student(id,name,age){this.id=id;// 构造函数继承Person.call(this,name,age);// 或者Person.apply(this,[name,age]);}// 原型链继承Student.prototype=new Person();Student.prototype.constructor=Person;/* 测试已省略,均为成功 */// 缺陷:父类的构造器执行了两次(new Person()、Person.call(···)),// 导致子类实例拥有两套父类属性,占用额外内存且代码不够优雅
寄生组合继承
优化组合继承中原型链继承部分,不必再创建父类的实例作为原型,只需一份父类显式原型的浅拷贝对象即可
/* Person */function Person(name,age){this.name=name;this.age=age;}Person.prototype.introduction=function(){console.log(name,age)}/* Student */function Student(id,name,age){this.id=id;// 构造函数继承Person.call(this,name,age);// 或者Person.apply(this,[name,age]);}// 优化·原型链继承Student.prototype=Object.create(Person.prototype);Student.prototype.constructor=Person;/* 测试已省略,如今babel将ES6类继承转换成ES5代码就是采用的寄生组合继承 */
