我创建了一个对象,我后来尝试将其用作原型。 对象的一个属性是数组。 我使用它作为原型创建了两个对象,并将一些元素推入第一个对象的数组中,为什么它们会显示在第二个对象的数组中,如何解决这个问题,谢谢。
请看代码:
var Category = { name: "", items: [], totalSpent: function(){ var total = 0; this.items.forEach(function(item){ sum += item.price; }); } }; var cat1 = Object.create(Category); var cat2 = Object.create(Category); cat1.items.push("item1"); console.log(cat2.items); //return ["item1"]I create an object, that I later am trying to use as a prototype. One of the properties of the object is an array. I create two objects using it as a prototype and push some elements into the array of the first one, why do they show up in the array of the second object and how do I fix that, thanks.
Please see the code:
var Category = { name: "", items: [], totalSpent: function(){ var total = 0; this.items.forEach(function(item){ sum += item.price; }); } }; var cat1 = Object.create(Category); var cat2 = Object.create(Category); cat1.items.push("item1"); console.log(cat2.items); //return ["item1"]最满意答案
Object.create不会生成对象的深层副本。 它将返回一个基于第二个参数的对象(如果没有给出第二个参数,则为空对象),第一个参数为原型。 如果然后改变该原型的成员,它将影响使用该对象作为原型的所有实例(在您的情况下为Category)。
cat1和cat2都是Category,因为它是原型; 所以:
cat1.__proto__ === cat2.__proto__;//true Category === cat1.__proto__;为了向您展示一个示例,您正在做什么而不涉及原型(注意:不要使用proto,它是非标准属性):
var org = {member:22}; // copy is a reference to org // same as cat1={};cat1.__proto__ = Category // or cat1 = Object.create(Category) var copy = org; // same as cat1.items.push('item'); // you are mutating Category.items so mutating Category copy.member=0;//mutating copy, so mutating org as well console.log(org.member);//=0随着原型涉及的事情变得有点复杂,因为重新分配成员实际上会影响该成员而不是改变原型,但上面的例子是为了简单。
var proto = {member:22,other:{sub:22}}; var copy = Object.create(proto); //this does not affect proto as it will shadow the member copy.member=0; //this will affect proto because you're mutating proto.other copy.other.sub=0;在您的情况下, items成员是特定于实例的,不应在原型上定义。 要初始化特定于实例的成员,可以使用构造函数或初始化实例的init函数,然后再使用它。
这里解释了如何使用原型,阴影等等。
Object.create does not make a deep copy of the object. It will return an object based on the second argument (or an empty object if second argument not given) with the first argument as it's prototype. If you then mutate members of that prototype it'll affect all instances that use that object as a prototype (in your case Category).
Both cat1 and cat2 have Category as it's prototype; so:
cat1.__proto__ === cat2.__proto__;//true Category === cat1.__proto__;To show you an example what you're doing without involving prototype (note: do not use proto, it's a non standard property):
var org = {member:22}; // copy is a reference to org // same as cat1={};cat1.__proto__ = Category // or cat1 = Object.create(Category) var copy = org; // same as cat1.items.push('item'); // you are mutating Category.items so mutating Category copy.member=0;//mutating copy, so mutating org as well console.log(org.member);//=0With prototype involved things get a little more complicated as re assigning members would actually shadow that member instead of changing the prototype but the above example was for simplicity.
var proto = {member:22,other:{sub:22}}; var copy = Object.create(proto); //this does not affect proto as it will shadow the member copy.member=0; //this will affect proto because you're mutating proto.other copy.other.sub=0;In your case the items member is instance specific and should not be defined on the prototype. To initialize instance specific members you can use constructor functions or an init function that initializes the instance before using it.
This, how prototype is used, shadowing and more is explained here.
更多推荐
发布评论