gpt4 book ai didi

javascript - 将实例属性放在原型(prototype)构造函数中,好还是坏?

转载 作者:行者123 更新时间:2023-12-03 11:30:49 25 4
gpt4 key购买 nike

我刚刚读完this关于 JavaScript 中原型(prototype)继承的非常好的文章,但令人惊讶的是作者如此强烈地反对在原型(prototype)中定义属性。

A common mistake when creating objects for the prototype chain, from programmers that come from classical OOP anyway, is to define common properties high up in the chain because they exist for all instances. We feel the need to define the property as if the abstract object described an interface. Yet there is no point in defining in a prototype a property that will be present in objects that descend from it. Javascript is not like Java : you don't declare in the base objects variables that will be different to all instances of the descendants. You declare a variable only on the level where it will be defined.

Take the name property of our animals. Since every animal has a name, it's natural to consider this property as common to all, and define it in the common denominator which is the Animal prototype. The thing is, Animal has no name. A Dog instance has a name.

In Javascript, you cannot say an Animal has a name. Animal is an object, not a definition, even if we use it like so. And that object has no name property. Why then is name referred to in Animal's methods if Animal has no name? Because Animal is abstract : it is not intended to be used by itself. this, in Animal, will never refer to Animal. It will refer to whatever object descends from Animal, dino for example. And dino has a name.

如果我有一组非常复杂的类,它们有许多共同的属性。我不明白如何更好地复制这些属性以及在每个可实例化派生类上设置它们的工作,因为这些工作可以在基类中完成一次,即使该基类本来就是“抽象”的.

例如:

function Analysis(args){
args = args || {};
// Extract supported init properties from args
this.description = args.description;
this.host = args.host;
this.source = args.source;
this.identifier = args.identifier;
this.vendor = args.vendor;
this.agent = args.agent;
//etc...
}

function PortfolioAnalysis(args){
Analysis.call(this, args);
args = args || {};
this.portfolio = args.portfolio;
this.author = args.author;
//etc...
}
PortfolioAnalysis.prototype = Object.create(Analysis.prototype);
PortfolioAnalysis.prototype.constructor = PortfolioAnalysis;

function TreatyAnalysis(args){
Analysis.call(this, args);
args = args || {};
this.treaty = args.treaty;
this.terms = args.terms;
//etc...
}
TreatyAnalysis.prototype = Object.create(Analysis.prototype);
TreatyAnalysis.prototype.constructor = TreatyAnalysis;

//etc...

所以文章说我应该将属性 descriptionhostsource 等的初始化代码粘贴到每个派生类,并将其从基类中删除。

我不明白为什么这更好,特别是如果使用这些共享属性构造这些对象有一堆复杂的通用逻辑,那么在基类中定义它们有什么不好的,如果它这么糟糕,是否有一个解决这个问题的方法不涉及代码重复或必须定义单独的“.init()”方法?

最佳答案

So the article is saying I should paste the initialization code for the properties description, host, source, etc. in each of the derived classes, and remove it from the base class.

没有。您的代码非常好,正是应该如何完成。

那篇文章说,诸如 descriptionhost 等属性应该放置在实例上(例如 new ThreatAnalysis(…) ,甚至是 new Analysis(…)),但不是Analysis.prototype 上 - 正是您正在做的事情。有些人会“默认”,例如Analysis.prototype 上的空、标识符等,因为它们想要“声明”每个 Analysis 实例都应该有一个标识符。正如文章所解释的,那是垃圾。

Analysis构造函数中共享您的初始化行为是可以的(正如本文提到的,共享函数可以放置在原型(prototype)链的较高位置)。无需内联它并进行分析和空对象,即使它是抽象的并且永远不会直接实例化。

关于javascript - 将实例属性放在原型(prototype)构造函数中,好还是坏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26741174/

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