07:17:40 AM

js深入之继承的多种方式和优缺点

February 08, 2022

文章导读

https://github.com/mqyqingfeng/Blog/issues/16

继承

原型链继承、借用构造函数、组合继承、原型式继承

继承的方式

  • 原型链继承:child构造函数的prototype指向parent的实例

    function Parent() {
    this.name = 'lili';
    }
    
    function Child() {}
    
    Child.prototype = new Parent();

    缺点:

    1. 引用类型的属性被所有实例共享

      function Parent() {
      this.names = ['lili'];
      }

    function Child() {}

    Child.prototype = new Parent();

    const child1 = new Child(); const child2 = new Child(); child1.names.push(‘kevin’); console.log(child1.names); // [‘lili’,‘kevin’]; child2.names.push(‘moli’); console.log(child2.names); // [‘lili’,‘kevin’,‘moli’];

    2. 在创建child实例时,不能向parent传参
    
    ---
  • 借用构造函数(经典继承):在child构造函数中执行Parent的call

    function Parent(name) {
      this.name = name;
    }
    
    function Child(name) {
      Parent.call(this, name);
    }
    
    const child1 = new Child('lili');
    console.log(child1.name); // lili
    const child2 = new Child('kevin');
    console.log(child2.name) // kevin

    优点:

    1. 避免引用类型的属性被所有实例共享
    2. 可以向parent传参

    缺点: 方法在构造函数中执行,每次创建实例都会创建一遍方法


  • 组合继承: 融合原型链继承和构造函数

    function Parent(name) {
      this.name = name;
      this.colors = ['green'];
    }
    
    function Child(name, age) {
      Parent.call(this, name);
      this.age = age;
    }
    
    Child.prototype = new Parent();
    Child.prototype.constructor = Child; // 修正Child.prototype,不然会是Parent
    
    const child1 = new Child('lili', 18);
    console.log(child1.name, child1.age, child1.colors);
  • 原型式继承:用object.create的模拟实现,将传入的对象作为创建的对象的原型

    function createObj(o) {
    function F() {};
    F.prototype = o;
    return new F();
    }
    
    var person = {
    name: 'kevin',
    friends: ['daisy', 'kelly']
    }
    
    var person1 = createObj(person);
    var person2 = createObj(person);
    
    console.log(person1, person2) // {} {}
    
    person1.name = 'person1';
    console.log(person2.name); // kevin
    
    person1.friends.push('taylor');
    console.log(person2.friends); // ["daisy", "kelly", "taylor"]

  • 寄生式继承:创建一个仅用于封装继承过程的函数,该函数在内部以某种形式来做增强对象,最后返回对象

    function createObj(o) {
    const F = Object.create(o);
    F.getName = function() {
      return 'kevin';
    }
    return F;
    }

百事可乐

Let it snow, let it snow, let it snow