Skip to content

JavaScript 继承的多种方式

原型链继承

javascript
function Parent() {
  this.name = "ZiJieYuan";
}

Parent.prototype.getName = function () {
  console.log(this.name);
};

function Child() {}

// 挂载prototype上;多个实例会共用
Child.prototype = new Parent();

Demo

javascript
var child1 = new Child();
console.log(child1.getName()); // ZiJieYuan

借用构造函数(经典继承)

javascript
function Parent() {
  this.names = ["ZiJieYuan", "SXF"];
}

function Child() {
  // 这里调用父类构造函数
  Parent.call(this);
}

demo

javascript
var child1 = new Child();

child1.names.push("VFrank");
console.log(child1.names); // ["ZiJieYuan", "SXF", "VFrank"]

var child2 = new Child();
console.log(child2.names); // ["ZiJieYuan", "SXF"]

组合继承

javascript
function Parent(name) {
  this.name = name;
  this.colors = ["red", "blue", "green"];
}

Parent.prototype.getName = function () {
  console.log(this.name);
};

function Child(name, age) {
  // 第二次执行 Parent;这一步可以消除 prototype 共用带来的问题
  Parent.call(this, name);

  this.age = age;
}

// 第一次执行 Parent
Child.prototype = new Parent();
Child.prototype.constructor = Child;

demo

javascript
var child1 = new Child("ZiJieYuan", "18");
child1.colors.push("black");

console.log(child1.name); // ZiJieYuan
console.log(child1.age); // 18
console.log(child1.colors); // ["red", "blue", "green", "black"]

var child2 = new Child("SXF", "20");

console.log(child2.name); // SXF
console.log(child2.age); // 20
console.log(child2.colors); // ["red", "blue", "green"]

原型式继承

javascript
function createObj(o) {
  function F() {}
  F.prototype = o;
  return new F();
}

demo

javascript
// 包含引用类型的属性值始终都会共享相应的值
var person = {
  name: "kevin",
  friends: ["daisy", "kelly"],
};

var person1 = createObj(person);
var person2 = createObj(person);

person1.name = "person1";
console.log(person2.name); // kevin

person1.friends.push("taylor");
console.log(person2.friends); // ["daisy", "kelly", "taylor"]

寄生式继承

javascript
function createObj(o) {
  var clone = Object.create(o);
  clone.sayName = function () {
    console.log("hi");
  };
  return clone;
}

寄生组合式继承

javascript
function object(o) {
  // 关键的三步
  function F() {}
  F.prototype = o;
  return new F();
}

function prototype(child, parent) {
  var prototype = object(parent.prototype);
  prototype.constructor = child;
  child.prototype = prototype;
}

// 当我们使用的时候:
prototype(Child, Parent);

总结

继承方式优点缺点
原型链继承-引用类型的属性被所有实例共享
借用构造函数1. 避免了引用类型的属性被所有实例共享
2. 可以在 Child 中向 Parent 传参
方法都在构造函数中定义,每次创建实例都会创建一遍方法
组合继承融合原型链继承和构造函数的优点-
原型式继承-包含引用类型的属性值始终都会共享相应的值
寄生式继承-每次创建对象都会创建一遍方法
寄生组合式继承1. 高效率体现它只调用了一次 Parent 构造函数
2. 原型链还能保持不变
3. 还能够正常使用 instanceof 和 isPrototypeOf
-

Released under the MIT License.