Skip to content

继承的方法和优缺点

原型链继承

实现方式:将子类的原型链指向父类的对象实例

原理:

  1. 子类实例child__proto__指向Child的原型链prototype
  2. Child.prototype 指向Parent类的对象实例
  3. 该父类对象实例的__proto__指向 Parent.prototype
  4. 所以Child可继承Parent的构造函数属性、方法和原型链属性、方法

优点:

  1. 可继承构造函数的属性,父类构造函数的属性,父类原型的属性
  2. 简单易懂,易于实现。

缺点:

  1. 所有子类实例共享父类的引用属性,修改一个实例的引用属性会影响其他实例。
  2. 无法向父类构造函数传递参数。
js
function Parent() {
  this.name = "Parent";
}

function Child() {
  this.age = 18;
}

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

const child = new Child();
console.log(child.name); // 输出 'Parent'
console.log(child.age); // 输出 18

构造函数继承

实现方式:在子类构造函数中使用call或者apply劫持父类构造函数方法,并传入参数

原理:使用call或者apply更改子类函数的作用域,使 this 执行父类构造函数,子类因此可以继承父类共有属性

优点:可解决原型链继承的缺点

缺点:不可继承父类的原型链方法,构造函数不可复用

js
function Parent(name, id) {
  this.id = id;
  this.name = name;
  this.printName = function () {
    console.log(this.name);
  };
}
Parent.prototype.sayName = function () {
  console.log(this.name);
};
function Child(name, id) {
  Parent.call(this, name, id);
  // Parent.apply(this, arguments);
}
var child = new Child("jin", "1");
child.printName(); // jin
child.sayName(); // Error

组合继承

原理:综合使用构造函数继承和原型链继承

优点:可继承父类原型上的属性,且可传参;每个新实例引入的构造函数是私有的

缺点:会执行两次父类的构造函数,消耗较大内存,子类的构造函数会代替原型上的那个父类构造函数

js
function Parent(name, id) {
  this.id = id;
  this.name = name;
  this.list = ["a"];
  this.printName = function () {
    console.log(this.name);
  };
}
Parent.prototype.sayName = function () {
  console.log(this.name);
};
function Child(name, id) {
  Parent.call(this, name, id); //第一次调用
  // Parent.apply(this, arguments);
}
Child.prototype = new Parent(); //第二次调用
var child = new Child("jin", "1");
child.printName(); // jin
child.sayName(); // jin

var a = new Child();
var b = new Child();
a.list.push("b");
console.log(b.list); // ['a']

原型式继承

原理:类似Object.create,用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象,结果是将子对象的__proto__指向父对象

缺点:共享引用类型

js
var parent = {
  names: ["a"],
};
function copy(object) {
  function F() {}
  F.prototype = object;
  return new F();
}
var child = copy(parent);

寄生式继承

原理:二次封装原型式继承,并拓展 优点:可添加新的属性和方法

js
function createObject(obj) {
  var o = copy(obj);
  o.getNames = function () {
    console.log(this.names);
    return this.names;
  };
  return o;
}

寄生组合式继承

原理:改进组合继承,利用寄生式继承的思想继承原型

优点:

  1. 只调用一次父类构造函数
  2. 继承父类原型链上的方法
js
function Parent(name) {
  this.name = name;
}

Parent.prototype.sayHello = function () {
  console.log("Hello, " + this.name);
};

function Child(name, age) {
  Parent.call(this, name); // 只调用一次父类构造函数
  this.age = age;
}

// 使用 Object.create 创建一个新的对象,并将其原型设置为 Parent.prototype
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

const child = new Child("Alice", 18);
child.sayHello(); // 输出 'Hello, Alice'

如有转载或 CV 的请标注本站原文地址