• js实现继承的方法中为何总是要修正constructor方法的指向呢?


    js实现继承的方法中为何总是要修正constructor方法的指向呢?

    问题引入

    最近看了许多关于js继承实现的相关文章,许多实现方式中都会存在这么一行代码:

    A.prototype.constructor = A

    于是感到好奇,这行代码的实际意义是什么?如果没有的话,还能达到继承的目的吗?

    前置知识

    为了熟悉javascript中与原型相关的几个基本概念,可以参看这篇文章JavaScript深入之从原型到原型链,作者写的十分简明易懂。

    读了文章以后可以知道,在方法(构造函数)上存在一个叫做prototype的属性,

    这个属性是一个对象;方法结合new关键字可以生成实例,生成的每一份实例上都会有一个叫做__proto__的属性,

    这个属性也是指向生成该实例的方法上的prototype属性;原型对象(即prototype这个对象)上也存在一个特别的属性,即constructor,这个属性指向的方法本身。

    回到问题本身

    我们先来回答第二个问题:如果没有这行代码,还能到达继承的目的吗?
    看一个常见的组合继承的实现方式,代码如下:

    function Animal(name) {
        this.name = name || '';
        console.log('Animal called.');
    }
    Animal.prototype.showName = function() {
        console.log('Name is: ', this.name);
    }
    function Cat(name, age) {
        Animal.call(this, name);
        this.age = age || 1;
        console.log('Cat called.');
    }
    Cat.prototype = new Animal();
    // Cat.prototype.constructor = Cat;    // 注释掉修正constructor方法的指向的这一行
    Cat.prototype.showAge = function() {
        console.log('Age is: ', this.age);
    }
    
    var cat = new Cat('meow', 3);
    console.log(cat.name);    // meow
    cat.showName();          // Name is: meow
    console.log(cat.age);    // 3
    cat.showAge();           // Age is: 3

    可以看到,继承的效果依然是达到了。所以,我觉得答案应该是能。

    我们再来看第一个问题,注释掉的这行代码的意义是什么呢?为什么大部分的实现方式中都建议我们修正这个constructor的指向呢?
    网上搜索后找到这篇文章: 为什么要做A.prototype.constructor=A这样的修正?,

    并由此进一步的查看了Stack Overflow上的这篇问答: What it the significance of the Javascript constructor property?
    所以,最重要的修正意义应该还是针对显示调用的时候。
    接着刚刚的代码来看:

    cat.__proto__.constructor 
    // 这个属性指向的应该是 Animal 构造函数,如果我们之前修正了constructor的指向的话,那么这里才会真的指向到 Cat 的构造函数 // 假设我们想要构造一个新的实例cat2,并且我们不知道对应的构造函数的名称是什么,不过好在我们刚刚已经有一个实例cat了(好吧,我知道这种假设比较2 -_-|||) var cat2 = new cat.__proto__.constructor(); // Animal called (这里只有Animal的构造函数被调用了) cat2.age; // undefined (因为在Animal构造函数中不存在age属性)

    好吧,我承认这种场景比较少见。但是,万一有呢?所以我的建议是,我们应该保留这种修正constructor的写法。

    后记

    在知乎的一篇问答中看到一种说法

    constructor其实没有什么用处,只是JavaScript语言设计的历史遗留物。由于constructor属性是可以变更的,所以未必真的指向对象的构造函数,只是一个提示。
    不过,从编程习惯上,我们应该尽量让对象的constructor指向其构造函数,以维持这个惯例。

    转载:https://www.ucloud.cn/yun/97020.html
    侵权告删


  • 相关阅读:
    mac下安装中文汉化插件和快速打开浏览器插件
    大数据基础---Flink_Data_Transformation
    大数据基础---Flink_Data_Source
    大数据基础---Flink开发环境搭建
    大数据基础---Flink核心概念综述
    大数据基础---Spark_Streaming整合Kafka
    大数据基础---Spark_Streaming整合Flume
    大数据基础---Spark_Streaming基本操作
    大数据基础---Spark_Streaming与流处理
    大数据基础---SparkSQL联结操作
  • 原文地址:https://www.cnblogs.com/zhangjiabing/p/13493271.html
Copyright © 2020-2023  润新知