• JavaScript面向对象那些东西-继承


    继承

    父类里有些属性方法 子类想把父类中的这些属性方法 继承过来给子类自己的实例也用用

    ( ps: →_→ 能不能专业点 没文化真可怕 )

    一、原型链继承

       // 原型链继承:把子类的原型作为父类的实例
       // 子类把父类中的私有和公有 都继承过来作为子类的原型属性(公有的)
       function A() {
           this.a = 123;
           this.say = function () {
               console.log('say');
           }
       }
       A.prototype.mess = 'mess';
       B.prototype = new A; // 将子类 的原型对象 重构为 父类A的实例
       B.prototype.constructor = B;
       console.log(B.prototype instanceof A);
       console.log(B.prototype.__proto__ === A.prototype);
       function B() {
       }
       var b1 = new B;
       var b2 = new B;
       console.log(b1);
       console.log(b1.a);
       console.log(b1.say === b2.say); //这个原型属性 是从父类的私有属性中继承过来的
       console.log(B.prototype.__proto__ === A.prototype);
       // 多态 子类重写父类 导致父类中所有实例都会受到影响
       B.prototype.__proto__.mess = '已经被子类修改了';
       
       var a1 = new A;
       console.log(a1.mess);
       
    复制代码

    二、借用构造函数

    // 借用构造函数
        // 把父类构造函数当做普通函数执行 将里面this修改为B类中实例
        // 这样的话父类中this.xxx 就相当于给我子类实例添加私有属性
        // 只能继承父类中私有属性
        function A() {
            this.a = 123;
            this.say = function () {
                console.log('say');
            }
        }
        A.prototype.mess = 'mess';
        function B() { // 子类中this 当前实例(子类的实例)
            A.call(this); // 把父类构造函数当做普通函数执行 将里面this修改为B类中实例
        }
        var b = new B;
        console.log(b);
        console.log(b.a);
        
    复制代码

    三、组合继承

    // 组合继承:原型链+借用构造函数继承
        // 原型链:把父类私有和公有 都继承为子类的公有属性
        // 借用构造函数:只能继承父类私有属性
        // 组合继承 缺点
        // 1.子类会把父类的实例属性继承过来两组 一组作为子类实例的私有属性 一组作为子类的公有属性
        // 2.父类会被调用俩次
        function A() {
            console.log(2222);
            this.a = 123;
            this.say = function () {
                console.log('say');
            }
        }
        A.prototype.mess = 'mess';
        B.prototype = new A; // 继承父类中原型属性(继承公有) 原型链继承是执行一次
        B.prototype.constructor = B;
        function B() {
            A.call(this); // 继承父类私有的 call继承时执行一次
        }
        var b = new B;
        console.log(b);
        console.log(b.a);
        console.log(b.mess);
        
    复制代码

    四、原型式继承

        // 原型式继承
        // Object.create();  创建一个新对象 然后 让这个新对象的__proto__指向这个传递进来的参数对象
        var obj1 = {name: 2, id: 1};
        var obj2 = Object.create(obj1); // obj2.__proto__ = obj1;
        // console.log(obj2.name);
        Object.myCreate = function (o) {
            // 创建一个临时构造函数
            function Fn() {
            }
            // 让这个临时构造函数 原型等于传递进来的对象
            Fn.prototype = o; // A.prototype
            return new Fn; // 返回这临时构造函数的实例 Fn的实例__proto__ = o
        };
        function A() {
            this.a = 123;
            this.say = function () {
                console.log('say');
            }
        }
        A.prototype.mess = 'mess';
    //    B.prototype = Object.create(A.prototype); // 创建一个新对象(并不是直接返回的A类的实例)作为子类的原型对象 并且这个对象__proto__ = A.prototype;
        // 继承父类公有的属性 作为 子类的公有属性
        // 将子类的 原型对象重构为 这个Fn的实例对象 并且这个实例__proto__ = A.prototype
        B.prototype = Object.myCreate(A.prototype);
        B.prototype.constructor = B;
        
        function B() {
            
        }
        var b = new B;
        console.log(b);
    
    复制代码

    五、寄生组合继承

        // 寄生组合继承 借用构造函数 + 原型式继承
        // 弥补 组合继承的缺点
        Object.myCreate = function (o) {
            function F() {
            }
            F.prototype = o;
            return new F;
        };
        function A() {
            this.a = 123;
            this.say = function () {
                console.log('say');
            }
        }
        A.prototype.mess = 'mess';
        // 通过原型式继承 将父类的 公有属性 继承为子类的公有属性
        // B.prototype = Object.create(A.prototype);
        B.prototype = Object.myCreate(A.prototype);
        B.prototype.constructor = B;
        function B() {
            A.call(this); // 将父类的私有属性继承为子类的实例的私有属性
        }
        var b = new B;
        console.log(b);
    
    
    复制代码

    六、冒充对象继承

    
        // 冒充对象继承:在子类构造函数中 生成一个父类的实例 然后把父类的实例当做一个普通对象 进行遍历 将遍历出来的私有和公有 复制一份 作为 子类的私有属性
        // 把父类的公有和私有 继承过来作为子类的私有属性
        function A() {
            this.a = 123;
            this.say = function () {
                console.log('say');
            }
        }
        A.prototype.mess = 'mess';
        function B() {
            var temp = new A;
            for(var k in temp){
               this[k] = temp[k];
            }
        }
        var b = new B;
        console.log(b)
        
    复制代码

    七、中间类继承

    // 中间类 IE 屏蔽了
        var arr = [11,22,13,14];
        arr.shift();
        console.log(arr.__proto__ === Array.prototype);
        console.log(arr.shift); // 通过arr的原型链能够找到这个方法
        console.log(arr instanceof Array);
        function sum() {
            arguments.__proto__ = Array.prototype;
    //      console.log(arguments instanceof Array);
            console.log(arguments.shift());
        }
        sum(1,34,5,6,5)
    复制代码

    八、ES6继承

    
    class Sub extends Super {
      constructor() {
        super()
      }
    }
    
    复制代码

    ES6继承其实是 寄生组合式继承实现,并将子类__proto__ 指向了父类本身

    "use strict";
    
    // 检验当前构造函数是否是通过new关键字调用
    function _classCallCheck(instance, Constructor) {
      if (!(instance instanceof Constructor)) {
        throw new TypeError("Cannot call a class as a function");
      }
    }
    
    function _possibleConstructorReturn(self, call) {
      if (!self) {
        throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
      }
      return call && (typeof call === "object" || typeof call === "function") ? call : self;
    }
    
    // 实现继承
    function _inherits(subClass, superClass) {
      if (typeof superClass !== "function" && superClass !== null) {
        throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
      }
      // 寄生组合继承
      subClass.prototype = Object.create(superClass && superClass.prototype, {
        constructor: {
          value: subClass,
          enumerable: false,
          writable: true,
          configurable: true
        }
      });
      // 子类__proto__指向父类
      if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
    }
    
    var Child = function (_Super) {
      _inherits(Child, _Super);
    
      function Child() {
        _classCallCheck(this, Child);
        
        // call继承
        return _possibleConstructorReturn(this, (Child.__proto__ || Object.getPrototypeOf(Child)).call(this));
      }
    
      return Child;
    }(Super);
    
    复制代码

    ES6方法 设置原型对象 Object.setPrototypeOf

    // 仅适用于Chrome和FireFox,在IE中不工作:
    Object.setPrototypeOf = Object.setPrototypeOf || function (obj, proto) {
      obj.__proto__ = proto;
      return obj; 
    }
    
    复制代码

    Object.create(proto, [propertiesObject]) 创建一个对象 并且这个对象的__proto__指向第一个参数proto

    let obj1 = {id: 1}
    let obj2 = Object.create(obj1)
    
    console.log(obj2.__proto__ === obj1) // true
    复制代码
  • 相关阅读:
    Linux(Ubuntu)安装Mujoco、mujoco-py的详细步骤、安装教程
    Model-Free Episodic Control
    Efficient Off-Policy Meta-Reinforcement Learning via Probabilistic Context Variables
    On First-Order Meta-Learning Algorithms
    Meta-Q-Learning
    Model-Agnostic Meta-Learning for Fast Adaptation of Deep Networks
    Meta Learning via Learned Loss
    Python不同版本切换
    Ubuntu下压缩解压文件
    Python写入CSV文件的问题
  • 原文地址:https://www.cnblogs.com/twodog/p/12136581.html
Copyright © 2020-2023  润新知