Skip to content
📁 标签
JavaScript

JS多种继承实现方式

类式继承

  • 原型中如果存在引用类型的数据,当修改一个实例时,其他实例中的值也会跟着改变
  • 实例化子类时,无法给父类传参
js
function SuperClass() {
  this.superValue = true;
  this.obj = {
    foo:'foo'
  }
}
SuperClass.prototype.getSuperValue = function() {
  return this.superValue;
}
function SubClass() {
  this.subValue = false;
}
SubClass.prototype = new SuperClass();
SubClass.prototype.getSubValue = function() {
  return this.subValue;
}
const instance = new SubClass();
console.log(instance)
console.log(instance.superValue) // true
console.log(instance.subValue) // false
console.log(instance instanceof SuperClass)// true
console.log(instance instanceof SubClass)// true
console.log(SubClass instanceof SuperClass)// false

构造函数继承

  • 必须在构造函数中定义方法,因此函数不能被复用
  • 子类不能访问父类的方法
js
function Person(name) {
  this.friends = ['张三','李四'];
  this.name = name;
}
Person.prototype.friends = function() {
  console.log(this.friends);
}
function Worker(name) {
  // 继承父类构造函数中的属性方法
  Person.call(this,name);
}
//创建第一个子类实例
const p1 = new Worker('王五');
//创建第二个子类实例
const p2 = new Worker('老六');
console.log(p1)
console.log(p2)
console.log(p1 instanceof Worker) // true

组合式继承

  • 父类构造函数会被调用两次
    • 第一次创建子类原型时
    • 第二次子类构造函数时
  • 子类包含父类所有实例属性
js
function Person(name) {
  this.friends = ['张三','李四'];
  this.name = name;
}
Person.prototype.friends = function() {
  console.log(this.friends);
}
function Worker(name) {
  // 继承父类
  Person.call(this,name);
  this.name=name
}
Worker.prototype=new Person()
Worker.prototype.getfriends=function(){
    console.log(this.friends);
}
//创建第一个子类实例
const p1 = new Worker('王五');
//创建第二个子类实例
const p2 = new Worker('老六');
console.log(p1)
console.log(p2)
console.log(p1.getfriends())
console.log(p1 instanceof Worker)

原型式继承

  • 属性中如果包含引用数据类型,会被共享
js
function inheritObject(o) {
    // 定义一个临时函数
    function F() {}
    //将函数的的原型继承父对象
    F.prototype = o;
    // 返回这个函数的实例,该对象的原型继承了父对象
    return new F();
}
function Person(name) {
    this.friends = ['张三','李四'];
    this.name = name;
}
Person.prototype.friends = function() {
    console.log(this.friends);
}
const p1=new Person('_island')
const p2 =inheritObject(p1)
// 等价于 Object.create(p1)
p2.name='_island(p2)'
console.log(p1.name)
console.log(p2.name)

寄生式继承

  • 在对象上添加函数,会导致后续不好复用
  • 类似构造函数方法
js
const obj1 = {
    name:'_island'
}
function createNewObj(obj) {
    // 通过原型方式创建新的对象
    const o = Object.create(obj);
    // 拓展新对象
    o.time = Date.now()
    // 返回拓展后的新对象
    return o;
}
const obj2=createNewObj(obj1)
console.log(obj1)
console.log(obj2)

寄生组合式继承

这个方法只调用了一次父级函数,也没有在子类原型上面添加多余的属性,与原来的原型链保持不变

  • 解决两次调用的方法是使用寄生组合式继承
js
function Person(name) {
  this.friends = ['张三','李四'];
  this.name = name;
}
Person.prototype.friends = function() {
  console.log(this.friends);
}
function Worker(name) {
  //继承父类
  Person.call(this,name);
  this.name=name
}
Worker.prototype=new Person()
Worker.prototype.getfriends=function(){
    console.log(this.friends);
}
//创建第一个子类实例
const p1 = new Worker('王五');
//创建第二个子类实例
const p2 = new Worker('老六');
console.log(p1)
console.log(p2)
console.log(p1.getfriends())
console.log(p1 instanceof Worker)