目录

1. 通过原型链实现继承
2. 借用构造函数继承
3. 寄生组合式继承

ES6 中的 class 类 可以通过 extends 关键字实现继承,而这道题,面试官可能更想问的是在 ES5 中如何实现

1. 通过原型链实现继承

javascript
// 父类: 公共属性和方法 function Person() { this.name = "yjw" } // 父类定义一个吃的方法 Person.prototype.eating = function() { console.log(this.name + ' is eating') } // 子类: 特有属性和方法 function Student() { this.sno = '001' } // Student的原型对象指向一个Person的实例对象per const per = new Person() Student.prototype = per // 子类定义一个学习的方法 Student.prototype.studying = function() { console.log(this.name + ' is studying') } const stu = new Student() console.log(stu) console.log(stu.name) // stu对象中没有name属性 会去他的原型对象per上找 per对象上有name属性 stu.eating() // stu对象中没有eating方法 会去他的原型对象per上找per对象上也没eating方法 再往上去per的原型对象上找 per的原型对象上有eating方法 stu.studying()

这种方式总结就是:子类的原型指向父类的一个实例对象

  • 原型链实现继承的弊端
  1. 通过直接打印对象是看不到这个属性的(继承属性看不到
  2. 属性被多个对象共享,如果这个属性是一个引用类型,会造成问题 (修改引用类型 会互相影响
  3. 不能给 Person 传递参数,因为这个对象是一次性创建的(没办法定制化

2. 借用构造函数继承

javascript
// 父类: 公共属性和方法 function Person(name) { this.name = name } // 父类定义一个吃的方法 Person.prototype.eating = function() { console.log(this.name + ' is eating') } // 子类: 特有属性和方法 function Student(name, sno) { // 借用了父类的构造函数 Person.call(this, name) this.sno = sno } // Student的原型对象指向一个Person的实例对象per const per = new Person() Student.prototype = per // 子类定义一个学习的方法 Student.prototype.studying = function() { console.log(this.name + ' is studying') }

借用构造函数继承解决了上面的三个问题。但还是不够完美

  • 存在的问题
  1. 会调用两次父类的构造函数
  2. 子类对象的原型对象上会多出没用的属性

3. 寄生组合式继承

javascript
// 父类: 公共属性和方法 function Person(name) { this.name = name } // 父类定义一个吃的方法 Person.prototype.eating = function() { console.log(this.name + ' is eating') } // 子类: 特有属性和方法 function Student(name, sno) { // 借用了父类的构造函数 Person.call(this, name) this.sno = sno } Student.prototype = Object.create(Person.prototype) // 原型式继承 不用new Person()多调用父类构造函数了 Object.defineProperty(Student.prototype, "constructor", { enumerable: false, configurable: true, writable: true, value: Student }) // 改构造函数名称 // 子类定义一个学习的方法 Student.prototype.studying = function() { console.log(this.name + ' is studying') }
javascript
// 上面的 Object.create(Person.prototype) 也可以写成 (兼容性) Object.setPrototypeOf(Student.prototype, Person.prototype) // 也可以写成 (兼容性) function object(o) { function F() {} F.prototype = o return new F() } Student.prototype = object(Person.prototype)
  • 注意:不要让子类型的原型对象 = 父类型的原型对象,因为这么做意味着以后修改了子类型原型对象的某个引用类型的时候, 父类型原生对象的引用类型也会被修改
如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:叶继伟

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!