在 javascript 中修改继承数组而不更改其父级的最佳方法是什么



我想创建一个从其他对象继承的对象。在构造子体时,我希望在不更改parent对象的情况下将一些项推送到继承的数组中。

假设我有一个叫篮子的物体:

function Basket(){
}

然后我这样填写:

Basket.prototype {
“price”: 5,
“contents” : [“apple”, “orange”, “grape”]
}

现在我想扩展一下。我想添加一些属性并更改一些属性。我做到了:

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

现在我想在contents属性中添加一个项,但只能在子实例中添加。

这出了问题:

this.contents.push(“banana”); 

看起来this.contents包含了对原型数组的引用,所以当把香蕉推到它上面时,意味着Bigbasket和Basket的实例也会在它们的内容中得到一根香蕉。因此,我首先复制了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.contents = Object.create(Basket.prototype.contents);
this.contents.push('banana');

这也很有效,而且似乎是一种更通用的方式。此外,在Chrome中,最后推送的项仅是子代的属性,而其余数组项是原型的属性。对我来说似乎很优雅。

尽管如此,这在我看来还是有点笨拙。我做错了吗?试图找出,但在扩展对象中找不到关于数组主题的任何内容。是否有一种方法可以使所有属性在实例化时都被复制而不被引用,从而生成子体?

谢谢!

您可以尝试以下操作:

  • 与其将pricecontent放在原型上,不如将它们作为Basket的属性
  • 继承BigBasket并将其原型设置为Basket的实例。这将允许您访问Basket的属性
  • BigBasket中定义一个私有变量content,其工作是维护子级的内容
  • 添加一个setter函数来变异这个变量

    • addContent:向孩子的内容添加新值
    • removeContentByIndex:根据索引移除值
    • getContent:这将返回content的副本以消除副作用。这也将允许您对内容进行自定义定义。在这种情况下,它自己的内容+父级的内容

    这将允许您定义一个API来与内容通信,还允许您创建一个公开的限制数据。暴露一切可能会引发问题。展示所需内容总是更好的。

注意:在原型上放置对象可能会导致问题,因为对象会产生副作用。您应该仅将"父"的值用作默认值。

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())

相关内容

最新更新