[英]What's the best way to modify an inherited array in javascript without changing its parent
I want to make an object that inherits from an other object.我想制作一个继承自其他 object 的 object。 In constructing the descendant, i want to push some items to an inherited array without changing the parentobject.
在构造后代时,我想在不更改父对象的情况下将一些项目推送到继承的数组中。
Say I have an object called basket:假设我有一个称为篮子的 object:
function Basket(){
}
Then i fill it like this:然后我像这样填充它:
Basket.prototype {
“price”: 5,
“contents” : [“apple”, “orange”, “grape”]
}
Now i want to extend this.现在我想扩展它。 I want to add some properties and change some.
我想添加一些属性并更改一些。 I did this:
我这样做了:
function BigBasket(){
this.price = 6; // change a property. This goes well, when an instance is created, price is still 5 in prototype and also in instances of Basket and it is 6 in the instance that is created from this descendant.
this.greetingcard = “Congratulations” // add a property. Goes well
Now i want to add an item to the contents-property but only in the descendant instances.现在我想在内容属性中添加一个项目,但只在后代实例中。
This goes wrong:这出错了:
this.contents.push(“banana”);
It seems this.contents contains a reference to the array of the prototype so when pushing a banana to it, means that instances of both Bigbasket and Basket get a banana in their contents as well.似乎 this.contents 包含对原型数组的引用,因此当将香蕉推送到它时,意味着 Bigbasket 和 Basket 的实例也会在其内容中获取香蕉。 Therefore i first made a copy of the Basket.contents (the parent contents) like this:
因此,我首先制作了 Basket.contents (父内容)的副本,如下所示:
this.contents = Object.getPrototypeOf(this).contents.slice(); // seems __proto__ is deprecated, so using getPrototypeOf here and then pushed the banana:
this.contents.push(‘banana’);
}
This seems to be working, but is this the right way?这似乎有效,但这是正确的方法吗? I know array is an object as well, so i tried this:
我知道数组也是 object,所以我尝试了这个:
this.contents = Object.create(Basket.prototype.contents);
this.contents.push('banana');
This works too and seems a more generic way.这也有效,似乎是一种更通用的方式。 Furthermore in Chrome the item that was pushed last was a property of only the descendant while the rest of the array-items were properties of the prototype.
此外,在 Chrome 中,最后推送的项目只是后代的属性,而数组项目的 rest 是原型的属性。 Seems elegant to me.
对我来说似乎很优雅。
Still, this looks a bit clumsy to me.不过,这对我来说看起来有点笨拙。 Am i doing this all wrong?
我做错了吗? Tried to find out but couldn't find anything on the topic of array's in extending objects.
试图找出但在扩展对象中找不到关于数组主题的任何内容。 Is there a way of making descendants where all properties are copied and not referenced when instanciated?
有没有一种方法可以使所有属性在实例化时都被复制而不被引用?
Thanks!谢谢!
You can try something like this:你可以尝试这样的事情:
price
and content
on prototype, make them as properties of Basket
.price
和content
放在原型上,而是将它们作为Basket
的属性。BigBasket
and set its prototype as instance of Basket
.BigBasket
并将其原型设置为Basket
的实例。 This will give you access to properties of Basket.content
in BigBasket
whose job will be to maintain the child's content.BigBasket
中定义一个私有变量content
,其工作是维护孩子的内容。 Add a setter function to mutate this variable添加一个设置器 function 来改变这个变量
addContent
: Add new values to child's content addContent
:向孩子的内容添加新值removeContentByIndex
: to remove value based on index. removeContentByIndex
:根据索引删除值。getContent
: This will return a copy of content
to nullify side effect. getContent
:这将返回content
的副本以消除副作用。 This will also allow you to have custom definition of content.this will allow you to define an API to communicate with content and also allows you to create a restrict data that is exposed.这将允许您定义 API 以与内容通信,还允许您创建公开的限制数据。 Exposing everything can cause issues.
暴露一切可能会导致问题。 Exposing what is required is always better.
暴露需要的东西总是更好的。
Note: Having objects on prototype can cause issues as objects will have side effect.注意:在原型上放置对象可能会导致问题,因为对象会产生副作用。 You should use Parent's values as default values only.
您应该只使用 Parent 的值作为默认值。
function Basket() { this.price = 5; this.contents = ["apple", "orange", "grape"] } function BigBasket() { const content = []; this.price = 6; this.greetingcard = "Congratulations"; this.addContent = function(value) { content.push(value); } this.removeContentByIndex = function(index) { content.splice(index, 1); } this.getContents = function() { return [].concat(this.__proto__.contents, content); } } BigBasket.prototype = new Basket(); const bb1 = new BigBasket(); const bb2 = new BigBasket(); bb1.addContent('banana'); console.log(bb1.getContents(), bb2.getContents())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.