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

更新日期: 2020-06-16阅读: 1.6k标签: 继承

问题引入

最近看了许多关于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 


原文地址:https://www.cnblogs.com/zhangjiabing/p/13493271.html  


链接: https://www.fly63.com/article/detial/9588

js原型继承、构造函数继承、组合继承法

原型继承缺点:1、不能由子对象像父对象传递参数,2、对于引用型的属性修改之后会印象其他的实例对象;构造函数继承缺点:1、不能继承父对象原型上的方法 2、每次实例化对象会重新构建函数,浪费内存。

各种实现js继承的方法总结

学过java的同学应该都知道,继承是java的重要特点之一,许多面向对象的语言都支持两种继承方式:接口继承和实现继承,接口继承只继承方法签名,而实现继承则继承实际的方法,在js中,由于函数没有签名,因此支持实现继承,而实现继承主要是依靠原型链来实现的,那么,什么是原型链呢?

css的继承性

在面向对象语言都会存在继承的概念,在面向对象语言中,继承的特点:继承了父类的属性和方法。那么我们现在主要研究css,css就是在设置属性的。不会牵扯到方法的层面。

js原型继承的几种方式

1. 原型链继承;2,构造函数继承(对象冒充继承);3,组合继承(原型链继承+构造函数继承);4,原型式继承;5. 寄生组合式继承,为了解决引用共享和超类型无法传参的问题,我们采用一种叫借用构造函数的技术

Js继承背后的场景-prototype,__proto__, [[prototype]]

prototype是构造函数的一个属性,它决定了在构造出来的对象上__proto__属性将是什么样的。如上图所示,理解JavaScript中的继承的关键是要理解母鸡如何产蛋的过程。

Js常用的继承方式

JavaScript常用继承方式主要分为(7种):原型链继承、构造函数继承、组合继承、原型式继承、寄生式继承、寄生组合继承以及继承多个对象。原型链继承(核心:将父类的实例作为子类的原型

JS之继承(ES5 & ES6)

继承到底是什么?继承(英语:inheritance)是面向对象软件技术当中的一个概念。如果一个类别B“继承自”另一个类别A,就把这个B称为“A的子类”,而把A称为“B的父类别”也可以称“A是B的超类”。继承可以使得子类具有父类别的各种属性和方法

Js继承总结

当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。如果让原型对象指向另一个类型的实例.....有趣的事情便发生了.

ES5 的构造函数原型链继承

构造函数,就是专门用来生成实例对象的函数。一个构造函数,可以生成多个实例对象,这些实例对象都有相同的结构。为了与普通函数区别,构造函数名字的第一个字母通常大写。

Js对象继承

JavaScript对象继承的方法有很多,这里总结一下几种比较常用的方法。使用call/apply和Object.create()第一种方法使用call或apply方法,改变了 this 的指向而实现继承,将父对象的构造函数绑定在子对象上,即在子对象构造函数中加一行

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!