Class Extends类继承

  1. /* ES6 类继承 */
  2. class Person{
  3. constructor(name,age){
  4. this.name=name;
  5. this.age=age;
  6. }
  7. introduce(){
  8. console.log(name,age)
  9. }
  10. }
  11. class Student extends Person{
  12. constructor(id,name,age){
  13. super(name,age);
  14. this.id=id;
  15. }
  16. }
  17. const stu=new Student(1,'rv',20);
  18. stu.introduce() // 'rv' 20

类继承原理实现

  • 原型链继承
  • 构造函数继承
  • 组合继承
  • 寄生组合继承

原型链继承

将父类的实例作为子类的原型

  1. /* Person */
  2. function Person(name,age){
  3. this.name=name;
  4. this.age=age;
  5. }
  6. Person.prototype.introduction=function(){
  7. console.log(name,age)
  8. }
  9. /* Student */
  10. function Student(id,name,age){
  11. this.id=id;
  12. }
  13. // 原型链继承
  14. Student.prototype=new Person('rv',20);
  15. Student.prototype.constuctor=Student;
  16. /* 测试 */
  17. const stu1=new Student(1,'rv',20);
  18. const stu2=new Student(2,'cw',10);
  19. // 缺陷1:实例化子类时,无法向父类传参,仅能通过修改原型链继承的Person实例传参
  20. console.log(stu1) // {id: 1}
  21. console.log(stu2) // {id: 2}
  22. stu1.introduce() // 'rv' 20
  23. stu2.introduce() // 'rv' 20
  24. // 缺陷2:引用值共享:由于共用相同Person实例作为原型,原型内父类的属性共享
  25. stu1.__proto__.name='foo';
  26. console.log(stu2.name) // 'foo'

构造函数继承

在子类构造函数内部通过apply()、call()、bind()调用父类构造函数,从而将父类构造函数绑定在子类上

  1. /* Person */
  2. function Person(name,age){
  3. this.name=name;
  4. this.age=age;
  5. }
  6. Person.prototype.introduction=function(){
  7. console.log(name,age)
  8. }
  9. /* Student */
  10. function Student(id,name,age){
  11. this.id=id;
  12. // 构造函数继承
  13. Person.call(this,name,age);
  14. // 或者Person.apply(this,[name,age]);
  15. }
  16. /* 测试 */
  17. const stu1=new Student(1,'rv',20);
  18. const stu2=new Student(2,'cw',10);
  19. console.log(stu1) // {id:1, name:'rv', age:20}
  20. console.log(stu2) // {id:2, name:'cw', age:10}
  21. // 缺陷1:无法获取到原型上的方法
  22. stu1.introduce() // undefined
  23. stu2.introduce() // undefined

组合继承

由于原型链继承实现了原型方法却缺少自身属性,而构造函数继承实现了自身属性却缺少原型方法,将其组合可互补缺陷

  1. /* Person */
  2. function Person(name,age){
  3. this.name=name;
  4. this.age=age;
  5. }
  6. Person.prototype.introduction=function(){
  7. console.log(name,age)
  8. }
  9. /* Student */
  10. function Student(id,name,age){
  11. this.id=id;
  12. // 构造函数继承
  13. Person.call(this,name,age);
  14. // 或者Person.apply(this,[name,age]);
  15. }
  16. // 原型链继承
  17. Student.prototype=new Person();
  18. Student.prototype.constructor=Person;
  19. /* 测试已省略,均为成功 */
  20. // 缺陷:父类的构造器执行了两次(new Person()、Person.call(···)),
  21. // 导致子类实例拥有两套父类属性,占用额外内存且代码不够优雅

寄生组合继承

优化组合继承中原型链继承部分,不必再创建父类的实例作为原型,只需一份父类显式原型的浅拷贝对象即可

  1. /* Person */
  2. function Person(name,age){
  3. this.name=name;
  4. this.age=age;
  5. }
  6. Person.prototype.introduction=function(){
  7. console.log(name,age)
  8. }
  9. /* Student */
  10. function Student(id,name,age){
  11. this.id=id;
  12. // 构造函数继承
  13. Person.call(this,name,age);
  14. // 或者Person.apply(this,[name,age]);
  15. }
  16. // 优化·原型链继承
  17. Student.prototype=Object.create(Person.prototype);
  18. Student.prototype.constructor=Person;
  19. /* 测试已省略,如今babel将ES6类继承转换成ES5代码就是采用的寄生组合继承 */