目錄:
  1. 准备
    1. 定义父类
      1. Object.create实现
      2. 拷贝继承
        1. 原型链继承
          1. 构造继承
            1. 寄生式继承
              1. 组合继承
                1. 寄生组合式继承
                  1. 参考

                    JavaScript的继承整理

                    閱讀時間:全文 1031 字,預估用時 6 分鐘
                    創作日期:2020-05-08
                    文章標籤:
                     
                    BEGIN

                    准备

                    定义父类

                    • 定义Father类和Mother类
                    • Father会下象棋
                    • Mother会做饭
                    • Father和Mother都会吃东西
                    function Father (name) {
                      this.name = name || 'Father';
                      this.gender = 'men';
                      this.chess = function () {
                        console.log(this.name, 'can chess!')
                      }
                    }
                    
                    Father.prototype.eat = function (food) {
                      console.log(this.name, 'eating', food);
                    }
                    
                    function Mother (name) {
                      this.name = name || 'Mother';
                      this.gender = 'women';
                      this.cook = function () {
                        console.log(this.name, 'can cook!')
                      }
                    }
                    
                    Mother.prototype.eat = function (food) {
                      console.log(this.name, 'eating', food);
                    }

                    Object.create实现

                    Object.create是ES5新增的方法, 在此之前可通过自己定义函数实现, 参考《JavaScript语言精粹》的实现:

                    function create (o) {
                      var F = function() {};
                      F.prototype = o;
                      return new F();
                    }

                    拷贝继承

                    function Child (name) {
                      var father = new Father();
                      for (var key in father) {
                        Child.prototype[key] = father[key];
                      }
                      var mother = new Mother();
                      for (var key in mother) {
                        Child.prototype[key] = mother[key];
                      }
                      Child.prototype.name = name || 'child';
                    }
                    • 通过对父类的实例化对象的属性和方法拷贝达到继承父类方法和属性
                    • 无法获取父类不可枚举方法和属性
                    var child = new Child();
                    console.log(child.name); // child
                    console.log(child.gender); // women
                    console.log(child.chess()); // child can chess!
                    console.log(child.cook()); // child can cook!
                    console.log(child.eat('fish')); // child eat fish
                    console.log(child instanceof Child); // true
                    console.log(child instanceof Father); // false
                    console.log(child instanceof Mother); // false

                    原型链继承

                    function Child () {};
                    Child.prototype = new Father();
                    Child.prototype.name = 'child';
                    • 也叫伪类继承
                    • 只能继承单一父类
                    • 原型对象的所有属性被所有实例共享.
                    • 通过修改prototype指向的方式实现继承, 指向实例化后的对象或者对象字面量, 即:
                      1. Child.prototype = new Father();
                      2. Child.prototype = { name: 'Father', ... };
                    var child = new Child();
                    console.log(child.name); // child
                    console.log(child.gender); // men
                    console.log(child.chess()); // child can chess!
                    console.log(child.eat('fish')); // child eating fish
                    console.log(child instanceof Child); // true
                    console.log(child instanceof Father); // true

                    构造继承

                    function Child (name) {
                      Father.call(this);
                      Mother.call(this);
                      this.name = name || 'child';
                    }
                    • 通过call调用达到父类实例方法和实例属性与当前this绑定
                    • 只继承父类的实例方法和属性(捆绑于this), 原型方法和属性无法继承
                    • 可以多继承
                    • 能继承弗雷的实例方法和属性, 却与父类无任何关系
                    var child = new Child();
                    console.log(child.name); // child
                    console.log(child.gender); // women
                    console.log(child.chess()); // child can chess!
                    console.log(child.cook()); // child can cook!
                    console.log(child.eat('fish')); // TypeError: child.eat is not a function
                    console.log(child instanceof Child); // true
                    console.log(child instanceof Father); // false
                    console.log(child instanceof Mother); // false

                    寄生式继承

                    // 实例方式实现, 生成伪类的实例化对象, 给对象增加属性并返回
                    function Child () {
                      var instance = new Father();
                      instance.name = 'child';
                      return instance;
                    }
                    
                    // 对象字面量方式实现, obj = { name: 'Father', ... }
                    function Child (obj) {
                      var instance = object(obj);
                      instance.name = 'child';
                      return instance;
                    }
                    • 也叫寄生式继承
                    • 返回的实例与中间函数不存在继承关系
                    • 寄生概念的理解: 创建一个仅用于封装继承过程的函数, 函数返回封装后的存在继承关系的主体
                    var child = Child();
                    // 或 var child = new Child();
                    console.log(child.name); // child
                    console.log(child.gender); // men
                    console.log(child.chess()); // child can chess!
                    console.log(child.eat('fish')); // child eating fish
                    console.log(child instanceof Child); // false
                    console.log(child instanceof Father); // true

                    组合继承

                    function Child (name) {
                      Father.call(this);
                      Mother.call(this);
                      this.name = name || 'child';
                    }
                    Child.prototype = new Father();
                    Child.prototype.constructor = Child;
                    • 组合继承其实就是将原型链继承和构造继承相结合
                    • 通过原型链继承方式解决构造继承方式无法继承原型方法和属性的问题
                    • 原型链继承只能继承一个父类
                    • 父类会执行2次
                    • 此继承继承了: this下属性和方法 + prototype下属性和方法 + this下属性和方法
                    var child = new Child();
                    console.log(child.name); // child
                    console.log(child.gender); // women
                    console.log(child.chess()); // child can chess!
                    console.log(child.cook()); // child can cook!
                    console.log(child.eat('fish')); // child eat fish
                    console.log(child instanceof Child); // true
                    console.log(child instanceof Father); // true
                    console.log(child instanceof Mother); // false

                    寄生组合式继承

                    function Child (name) {
                      Father.call(this);
                      Mother.call(this);
                      this.name = name || 'child';
                    }
                    Child.prototype = create(Father.prototype);
                    Child.prototype.constructor = Child;
                    • 也叫组合寄生继承
                    • 和组合继承的差别在于避免重复实例化或执行父类, 和组合式继承相比不用继承实例化对象的属性和方法, 因为也没必要
                    • 此继承继承了: this下属性和方法 + prototype下属性和方法
                    var child = new Child();
                    console.log(child.name); // child
                    console.log(child.gender); // women
                    console.log(child.chess()); // child can chess!
                    console.log(child.cook()); // child can cook!
                    console.log(child.eat('fish')); // child eat fish
                    console.log(child instanceof Child); // true
                    console.log(child instanceof Father); // true
                    console.log(child instanceof Mother); // false

                    参考

                    FINISH

                    隨機文章
                    人生倒計時
                    default