zoukankan      html  css  js  c++  java
  • 温习js中对象的继承

    温故而知新 XD

    1. 关于原型和构造函数的几个知识要点:

    1. 使用new 操作符调用构造函数,会经历以下四个步骤:
      1.1. 创建一个新对象;
      1.2. 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
      1.3. 执行构造函数中的代码(为这个新对象添加属性);
      1.4. 返回新对象。
    2. 当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性:__proto__),指向构造函数的原型对象(所以可以在构造函数的 prototype 里存放实例公用的方法)。
    3. 每当代码读取某个对象的某个属性时,都会进行一次搜索,目标是具有给定名字的属性。搜索从对象实例本身开始。如果在实例中找到了该属性,则 return 该属性的值;如果没有找到,则搜索内部指针指向的原型对象( __proto__ ),若找到,则 return 该属性值;若没找到,继续搜索原型的原型...

    2. 实现

    给出父类 Animal,实现子类Cat:

    function Animal (name) {
        this.name = name
        this.brother = 'Tony'
    }
    
    Animal.prototype.eat = function (thing) {
        console.log(this.name + ' eat ' + thing);
    }
    

    2.1 组合继承(结合原型链和借用构造函数,不太完美)

    function Cat (name) {
        Animal.call(this,name)   // 借用构造函数,继承父类属性
        this.sister = 'May'
    }
    
    Cat.prototype = new Animal()   // 原型链,继承父类方法
    /* 在prototype继承了父类实例的全部属性,存在冗余。属性的继承已经在构造函数内通过调用父类构造函数实现。
    实际上,子类的prototype需要的只是父类实例中指向父类原型的内部指针: Cat.prototype.__proto__ =  Animal.protype   */
    
    console.log(Cat.prototype)
    //  {name: undefined(冗余), brother: "Tony"(冗余), constructor: ƒ}
    
    Cat.prototype.constructor = Cat    // 由于上面 Cat.prototype 进行了赋值,所以需要重新指定其构造函数。
    // 这一步对 instanceof 无影响,因为  "instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性" ;影响的是Cat实例的constructor 属性。
    // 如果不做这一步:var Tom = new Cat('Tom'); Tom.constructor  ==>  Animal  
    
    

    2.2 寄生组合继承(完美)

    function Cat (name) {
        Animal.call(this,name)
        this.sister = 'May'
    }
    
    function createObject (obj) {  /* 创建一个新对象,使用现有的对象来提供新创建的对象的__proto__ ,相当于 Object.create()  */
        function F () {}
        F.prototype = obj
        return new F()    
    }
    
    Cat.prototype = createObject (Animal.prototype)
    // 相当于 Cat.prototype = Object.create(Animal.prototype)
    
    console.log(Cat.prototype)
    //  {constructor: ƒ}
    
    Cat.prototype.constructor = Cat
    
    

    2.3 ES6语法

    class Animal {
      constructor(name){
        this.name = name
        this.brother = 'Tony'
      }
    
      eat(thing) {
        console.log(this.name + ' eat ' + thing);
      }
    }
    
    class Cat extends Animal {
      constructor(name) {
        super(name)  
        /* super()表示调用父类构造函数,this指向子类。只有调用super之后,才可以使用this关键字,否则新建实例时会报错。*/
        /* 另:super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。通过super调用父类方法时,方法内部this指向子类;对super的猴哥属性赋值时,super就是this,赋值的属性会变成子类实例的属性 (不清楚里面是什么魔法)*/
    
        this.sister = 'May'
      }
    } 
    
    
  • 相关阅读:
    第八章 路由器交换机及其操作系统的介绍
    k-Tree DP计数
    Drop Voicing 最长升序
    高精度
    1196D2
    C
    POJ 3974 马拉车
    2020.8.1第二十六天
    2020.7.31第二十五天
    每日日报
  • 原文地址:https://www.cnblogs.com/JRliu/p/9222473.html
Copyright © 2011-2022 走看看