Skip to content

JavaScript继承


1. 原型链继承

思路:将父类的实例作为子类的原型

优点:父类方法可以复用

缺点:父类的所有引用属性会被所有的子类共享,更改一个子类的引用属性,其他子类也会受影响;子类型实例不能给父类型构造函数传参。

javascript
function Parent() {
  this.isShow = true;
  this.info = {
    name: 'wp',
    age: 18
  }
}
function Child() {}
Child.prototype = new Parent()

// Test
let child1 = new Child()
let child2 = new Child()

console.log(child1.info.name) // 可以访问到父类的引用属性,'wp'
child1.info.name = 'wp2'
console.log(child2.info.name) // 修改一个引用属性后,其他子类也会受影响

2. 构造函数继承

思路:在子类构造函数中调用父类构造函数,可以在子类构造函数中使用callapply方法

优点:可以在子类构造函数中向父类传参数;父类的引用属性不会被共享

缺点:子类不能访问父类原型上(Parent.prototype)的方法,因此所有方法属性都写在构造函数中,每次创建实例都会初始化。

javascript
function Parent() {
  this.info = {
    name: 'wp',
    age: 18
  }
}
function Child() {
  Parent.call(this)
}

// Test
let child1 = new Child()
let child2 = new Child()

child1.info.gender = '男'
console.log(child1.info) // {name: 'wp', age: 18, gender: '男'}

console.log(child2.info) // {name: 'wp', age: 18}

// 传递参数
function Parent(name) {
    this.info = { name: name };
}
function Child(name) {
    //继承自Parent,并传参
    Parent.call(this, name);
    
     //实例属性
    this.age = 18
}

let child1 = new Child("yhd");
console.log(child1.info.name); // "yhd"
console.log(child1.age); // 18

let child2 = new Child("wxb");
console.log(child2.info.name); // "wxb"
console.log(child2.age); // 18

3. 组合继承

思路:综合原型链继承和构造函数继承的优点。使用原型链继承原型上的属性和方法,通过构造函数继承实例属性,这样既可以把方法定义在原型上以实现重用,又可以每个实例都有自己的属性。

优点:父类的方法可以复用;可以在Child构造函数中向Parent构造函数中传参;父类构造函数中的引用属性不会被共享。

javascript
function Parent(name) {
  this.name = name;
  this.colors = ['red', 'blue', 'yellow'];
}
Parent.prototype.sayName = function () {
  console.log(this.name);
}

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

4. 原型式继承

思路:对参数对象浅复制

优点:父类方法可复用

缺点:父类的引用会被所有子类所共享;子类实例不能向父类传参

javascript
function objectCopy(obj) {
  function Fn() {};
  Fn.prototype = obj;
  return new Fn()
}
// 效果类似Object.create()

5. 寄生式继承

思路:构造函数+工厂模式。使用原型式继承对一个目标对象进行浅复制,增强浅复制的能力。

javascript
function objectCopy(obj) {
  function Fun() { };
  Fun.prototype = obj;
  return new Fun();
}

function createAnother(original) {
  let clone = objectCopy(original);
  clone.getName = function () {
    console.log(this.name);
  };
  return clone;
}

6. 寄生组合继承

优点:只调用一次父类构造函数;Child可以向Parent传参;父类方法可以复用;父类的引用属性不会被共享。寄生式组合继承。

javascript
function objectCopy(obj) {
  function Fun() { };
  Fun.prototype = obj;
  return new Fun();
}

function inheritPrototype(child, parent) {
  let prototype = objectCopy(parent.prototype); // 创建对象
  prototype.constructor = child; // 增强对象
  Child.prototype = prototype; // 赋值对象
}

function Parent(name) {
  this.name = name;
  this.friends = ["rose", "lily", "tom"]
}

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

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

inheritPrototype(Child, Parent);
Child.prototype.sayAge = function () {
  console.log(this.age);
}

7. 补充:ES6的extend语法

参考链接:掘金-JS继承