zoukankan      html  css  js  c++  java
  • JS 详解对象的继承

    在学习这篇博文前,请先移步我的另外一篇博文:JS 一张图理解prototype、proto和constructor的关系,先弄清楚“原型链”,这样对于理解继承会非常有效。

    注意:博文中提到的“属性”,指的是“属性+方法”,这里统称为“属性”;

    一、构造函数继承

    var obj = new Object();   使用构造函数new一个对象实例(所以程序员天天都在谈对象,哈哈哈)

    特点:

    • 实例对象继承父类的共有属性和私有属性

    来个实例加深理解:

    function Animal() {
        this.type = '动物';
    }
    Animal.prototype.getType = function(){
        console.log(this.type);
    }
    let animal = new Animal();
    console.log(animal.type);  // 动物
    animal.getType(); // 动物

    二、原型链继承

    Child.prototype = new Parent();   将父类的实例作为子类的原型

    特点:

    • 子类的prototype上的所有属性将被完全覆盖,所以子类的prototype属性应该在覆盖后重新定义;
    • 子类的constructor指向父类,为了构造函数的完整性,需要重新指定子类的constructor属性,方法:Child.prototype.constructor = Child;
    • 修改子类与父类同名的属性,不会修改父类的属性;这是因为父类的属性在子类的原型链上,且这些属性相当于是子类的__prototype__或者更加上一级。(这里如果理解不了,说明没理解透 JS 一张图理解prototype、proto和constructor的关系 这篇文章)
    原型继承,并不是把父类的属性和方法COPY一份给子类,而是让子类的原型和父类原型之间搭建一个链接的桥梁,以后子类(或者子类的实例),可以通过原型链的查找机制,找到父类原型上的方法,从而调取这些方法使用即可。

    来个实例加深理解:

    function Animal() {
        this.type = '动物';
    }
    Animal.prototype.getType = function(){
        console.log(this.type);
    }
    function Cat(){
        this.vary = '';
    }
    Cat.prototype.getVary = function(){
        console.log(this.vary);
    }
    Cat.prototype = new Animal();
    var cat = new Cat();
    // cat.getVary() // 报错:cat.getVary is not a function [原因:Cat.prototype = new Animal()的操作覆盖了原型链]
    console.log(cat.constructor); // Animal 这个constructor实质调用的是Animal.prototype.constructor
    
    // 修改Cat类的constructor为Cat
    Cat.prototype.constructor = Cat;
    console.log(cat.constructor); // Cat
    
    cat.getType(); // 动物
    // 修改Cat类prototype上的getType方法,看是否影响Animal类的getType方法
    Cat.prototype.getType = function(){
        console.log('我是猫科类');
    }
    var animal = new Animal();
    animal.getType(); // 动物

     三、call、apply、bind继承

    在子类的构造体中,使用call、apply、bind方法,让父类方法中的this指向子类的实例,也就是改变this的上下文环境。

    特点:

    • 子类构造体继承父类的私有属性(继承完成后,子类和父类是没关系的)

    先来个call实现原理,很重要的哦

    Function.prototype.call2 = function () {
      var ary = [...arguments].slice(1);
      if (!arguments[0]) {
        this(...ary);
      } else {
        var obj = Object(arguments[0]); // 将参数变成一个对象
        obj.__proto__.fn = this;
        obj.fn(...ary);
        delete obj.__proto__.fn;
      }
    };

    来个实例加深理解:

    function Animal() {
        this.type = '动物';
    }
    Animal.prototype.getType = function(){
        console.log(this.type);
    }
    function Cat(){
        Animal.call(this);
        this.vary = '';
    }
    Cat.prototype.getVary = function(){
        console.log(this.vary);
    }
    var cat = new Cat();
    console.log(cat.type); // 动物
    // cat.getType(); // Uncaught TypeError: cat.getType is not a function
    cat.type = '猫科动物';
    var animal = new Animal();
    console.log(animal.type); // 动物

     四、寄生组合继承

    var child = Object.create(obj, props); 

    • obj:一个对象,应该是新创建的对象的原型。
    • props:可选。该参数对象是一组属性与值,该对象的属性名称将是新创建的对象的属性名称,值是属性描述符

    我先来一段Object.create的实现方式(看懂原理很重要)

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

    我们这里只分析参数obj的骚操作,可以看出来,Object.create是内部定义一个对象,并且让F.prototype对象赋值为引进的对象/函数 o,并return出一个对象的实例。

    只要看懂了原理,我们可以参考“原型链继承”的方式去理解这种继承方法;

    来个实例加深理解:

    function Animal() {
        this.type = '动物';
    }
    Animal.prototype.getType = function(){
        console.log(this.type);
    }
    
    var cat = Object.create(new Animal(), {
        vary: {
            value: '猫科动物'
        }
    });
    console.log(cat.constructor); // Animal 这个constructor实质调用的是Animal.prototype.constructor
    console.log(cat.type); // 动物
    cat.getType(); // 动物
    console.log(cat.vary); // '猫科动物'
  • 相关阅读:
    设计一个smartnic
    lshw
    VF PF Reset Tests
    iommu dmar 和虚拟机
    2019-10-31-win10-uwp-访问解决方案文件
    2019-10-31-win10-uwp-访问解决方案文件
    2019-8-31-dotnet-使用-Environment.FailFast-结束程序
    2019-8-31-dotnet-使用-Environment.FailFast-结束程序
    docker dead but pid file exists 问题
    java数据结构(二叉树)
  • 原文地址:https://www.cnblogs.com/minigrasshopper/p/9150470.html
Copyright © 2011-2022 走看看