前端面试题 - 90. JS实现继承的方式

177 阅读3分钟

继承方式

  1. 原型链继承
function Parent() {
  this.name = 'Parent';
}

Parent.prototype.sayName = function () {
  console.log('My name is ' + this.name);
};

function Child() {}

Child.prototype = new Parent();

var child1 = new Child();
child1.sayName(); // My name is Parent
  1. 构造函数继承
function Parent(name) {
  this.name = name;
}

function Child(name) {
  Parent.call(this, name);
}

var child1 = new Child('Child');
console.log(child1.name); // Child
  1. 组合继承
function Parent(name) {
  this.name = name;
}

Parent.prototype.sayName = function () {
  console.log('My name is ' + this.name);
};

function Child(name) {
  Parent.call(this, name);
}

Child.prototype = new Parent();
Child.prototype.constructor = Child;

var child1 = new Child('Child');
child1.sayName(); // My name is Child
  1. 原型式继承
function createObj(obj) {
  function F() {}
  F.prototype = obj;
  return new F();
}

var parent = {
  name: 'Parent',
  sayName: function () {
    console.log('My name is ' + this.name);
  }
};

var child1 = createObj(parent);
child1.name = 'Child';
child1.sayName(); // My name is Child
  1. 寄生式继承
function createObj(obj) {
  var clone = Object.create(obj);
  clone.sayName = function () {
    console.log('My name is ' + this.name);
  };
  return clone;
}

var parent = {
  name: 'Parent'
};

var child1 = createObj(parent);
child1.name = 'Child';
child1.sayName(); // My name is Child
  1. 寄生组合式继承
function Parent(name) {
  this.name = name;
}

Parent.prototype.sayName = function () {
  console.log('My name is ' + this.name);
};

function Child(name) {
  Parent.call(this, name);
}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

var child1 = new Child('Child');
child1.sayName(); // My name is Child

优缺点

这些继承方式有各自的优缺点和应用场景:

  1. 原型链继承 优点:简单易懂,易于实现。 缺点:父类中引用类型的属性会被所有子类共享,在子类中修改该属性会影响所有子类。 应用场景:适用于单一对象的继承。
  2. 构造函数继承 优点:可以避免父类中引用类型的属性被所有子类共享的问题。 缺点:无法继承父类原型上的属性和方法,每个子类都会有一个父类的副本。 应用场景:适用于多个相似对象的继承。
  3. 组合继承 优点:结合了原型链继承和构造函数继承的优点,既能够继承父类原型上的属性和方法,又能够避免父类中引用类型的属性被所有子类共享的问题。 缺点:调用了两次父类构造函数,导致父类的实例属性和子类的实例属性重复。 应用场景:通用的继承方式,适用于大多数情况。
  4. 原型式继承 优点:简单方便,可以在不必创建自定义类型的情况下实现继承。 缺点:与原型链继承一样,父类中引用类型的属性会被所有子类共享,在子类中修改该属性会影响所有子类。 应用场景:适合在一个对象基础上创建新对象,或者在不想创建构造函数的情况下实现继承。
  5. 寄生式继承 优点:可以在不必创建自定义类型的情况下实现继承,并且可以向已有对象添加方法和属性。 缺点:同样存在与原型链继承相同的问题,即父类中引用类型的属性会被所有子类共享,在子类中修改该属性会影响所有子类。 应用场景:适合在一个对象基础上创建新对象,并且需要封装继承过程的情况。
  6. 寄生组合式继承 优点:避免了组合继承中调用两次父类构造函数的问题,既能够继承父类原型上的属性和方法,又能够避免父类中引用类型的属性被所有子类共享的问题。 缺点:略显繁琐,需要对父类原型进行一次浅拷贝。 应用场景:通用的继承方式,是组合继承的一种优化方案。