gpt4 book ai didi

javascript - javascript中prototype.constructor的实际使用

转载 作者:行者123 更新时间:2023-11-30 16:51:31 26 4
gpt4 key购买 nike

简单来说,为什么我们使用 prototype.constructor。我正在阅读一篇关于继承的文章,其中我看到了 prototype.constructor。当我评论该代码时,我看不出结果有什么不同。所以我的问题是为什么以及何时实际使用它。

function Mammal(name){ 
this.name=name;
this.action= function (){
alert('0')
}

}



function Cat(name){
this.name=name;
}

Cat.prototype = new Mammal();

//Cat.prototype.constructor=Cat; // Otherwise instances of Cat would have a constructor of Mammal



Cat.prototype.action=function(){
alert('1')
}

var y= new Mammal()
var x= new Cat()

y.action()

x.action()

最佳答案

主要是惯例。尽管 JavaScript 本身没有使用 constructor 属性,但有时人们会在他们的代码中使用它,假设它将返回引用对象的构造函数。 这不再只是约定,请参阅 ¹ 了解详细信息.

创建函数时:

function Cat() {
}

该函数以其 prototype 属性上的一个对象开始,该对象具有一个名为 constructor 的属性,该属性指向函数:

console.log(Cat.prototype.constructor === Cat); // true

这在规范中。 (这也是规范中唯一提到属性的地方——例如,JavaScript 本身根本不使用此属性。 不再是。¹)

因此,使用该原型(prototype)创建的实例(无论是通过构造函数还是其他方式创建)都继承了该 constructor 属性:

var c = new Cat();
console.log(c.constructor === Cat); // true

var c2 = Object.create(Cat.prototype);
console.log(c2.constructor === Cat); // true, even though Cat wasn't used

当你替换一个函数的 prototype 属性时,就像你在构建层次结构时通常做的那样:

Cat.prototype = new Mammal(); // This is an anti-pattern, btw, see below

...您最终在 Cat.prototype 上得到一个对象,其中 constructor 指向 Mammal。由于这不是人们通常所期望的,因此通常会修复它:

Cat.prototype.constructor = Cat;

虽然 JavaScript 本身没有使用该属性(它现在使用了¹),但有时人们会在他们的代码中使用它,假设它会引用回对象的构造函数。


Re the anti-pattern in that code: When using constructor functions to build a hierarchy, it's not best practice to actuallycall "base"constructor to create the "derived"constructor's 原型(prototype)。相反,使用 Object.create 来创建原型(prototype):

Cat.prototype = Object.create(Mammal.prototype);
Cat.prototype.constructor = Cat;

...然后链接到 Cat 中的 Mammal:

function Cat() {
Mammal.call(this);
// ...
}

为什么要这样做?考虑一下:如果基类需要参数,直到构造时间才有意义地初始化一个实例,你才会得到这些参数怎么办?在拥有参数之前,您不能将其传递给它。上面的模式允许您处理这种情况。

请注意 Object.create 是在 ES5 中添加的,因此在某些旧浏览器(如 IE8)中缺失。不过,它的单参数版本可以简单地填充/填充:

if (!Object.create) {
Object.create = function(proto, props) {
if (typeof props !== "undefined") {
throw new Error("The second argument of Object.create cannot be shimmed.");
}
function f() { }
f.prototype = proto;
return new f;
};
}

我只想指出,构造函数只是在 JavaScript 中构建对象层次结构的一种方法。它们不是唯一的方法,因为 JavaScript 使用原型(prototype)继承。 JavaScript 是如此强大,您可以使用构造函数来获得类似于类继承的东西,但它也可以让您直接进行更传统的原型(prototype)式继承。


¹ “虽然 JavaScript 本身没有使用 constructor 属性......” 从 ES2015(又名“ES6”)开始,这不再是真的了。现在,constructor 属性被用在几个地方(例如 SpeciesConstructorArraySpeciesCreate 抽象操作),它们被用在各种具有返回类新实例的方法的类中,例如 Array#slicePromise#then。它用在那些地方以确保子类正确工作:例如,如果您将 Array 子类化,并在子类的实例上使用 slice,则 返回的数组slice 是您的子类的实例,而不是原始 Array — 因为 slice 使用 ArraySpeciesCreate。

关于javascript - javascript中prototype.constructor的实际使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30453915/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com