设置属性时设置所有具有相同名称的属性的Javascript对象

时间:2018-06-23 08:21:47

标签: javascript node.js object

我直到最近才开始使用javascript和NodeJ。 我面临一个简单的问题,我发现很难找到在线答案。 我正在初始化一个对象,其中包含许多产品,每个产品都有价格和可用性。当我尝试设置一种产品的价格时,它会设置所有产品的价格,而不仅仅是我想要设置的一种。我究竟做错了什么?

var ProdStruct = {
  'price' : 0,
  'available' : 0,
};
var Prods = {
  '1' : ProdStruct,
  '2' : ProdStruct,
  '3' : ProdStruct,
  '4' : ProdStruct,
  '5' : ProdStruct,
  '6' : ProdStruct,
  '6' : ProdStruct,
  '7' : ProdStruct
};
Prods['6']['price'] = 99;
console.log(Prods);

输出:

{ '1': { price: 99, available: 0 },
  '2': { price: 99, available: 0 },
  '3': { price: 99, available: 0 },
  '4': { price: 99, available: 0 },
  '5': { price: 99, available: 0 },
  '6': { price: 99, available: 0 },
  '7': { price: 99, available: 0 } }

1 个答案:

答案 0 :(得分:5)

您只有一个 ProdStruct对象,您引用了七次。也就是说,您的内存中有这样的内容:

                                        +−−−−−−−−−−−−−−+
ProdStruct−−−−−−−−−−−−−−+−+−+−+−+−+−+−−>|   (object)   |
                       / / / / / / /    +−−−−−−−−−−−−−−+
                       | | | | | | |    | price: 0     |
                       | | | | | | |    | available: 0 |
                       | | | | | | |    +−−−−−−−−−−−−−−+
         +−−−−−−−−−−+  | | | | | | |
Prods−−−>| (object) |  | | | | | | |
         +−−−−−−−−−−+  | | | | | | |
         | 1        |−−+ | | | | | |
         | 2        |−−−−+ | | | | |
         | 3        |−−−−−−+ | | | |
         | 4        |−−−−−−−−+ | | |
         | 5        |−−−−−−−−−−+ | |
         | 6        |−−−−−−−−−−−−+ |
         | 7        |−−−−−−−−−−−−−−+
         +−−−−−−−−−−+

修改该对象的状态(更改price)将修改其状态;使用七个引用中的哪个来进行更改或查看结果并不重要,它只是一个对象。

您需要对对象进行复制以获得所需的结果。一种方法是使用Object.assign

var ProdStruct = {
  'price' : 0,
  'available' : 0,
};
var Prods = {
  '1' : Object.assign({}, ProdStruct),
  '2' : Object.assign({}, ProdStruct),
  '3' : Object.assign({}, ProdStruct),
  '4' : Object.assign({}, ProdStruct),
  '5' : Object.assign({}, ProdStruct),
  '6' : Object.assign({}, ProdStruct),
  '6' : Object.assign({}, ProdStruct),
  '7' : Object.assign({}, ProdStruct)
};
Prods['6']['price'] = 99;
console.log(Prods);
.as-console-wrapper {
  max-height: 100% !important;
}

...但是我认为在您的情况下,我可能只拥有一个构造函数:

function Prod() {
  this.price = 0;
  this.available = 0;
}
var Prods = {
  '1' : new Prod(),
  '2' : new Prod(),
  '3' : new Prod(),
  '4' : new Prod(),
  '5' : new Prod(),
  '6' : new Prod(),
  '6' : new Prod(),
  '7' : new Prod()
};
Prods['6']['price'] = 99;
console.log(Prods);
.as-console-wrapper {
  max-height: 100% !important;
}

作为Rick mentioned in a comment,您可以让构造函数接受参数:

function Prod(price, available) {
  this.price = price || 0;
  this.available = available || 0;
}

在这种情况下,如果您不提供priceavailable,它将具有值undefined,并且该代码使用通用的成语something || default来使用{ {1}}代替了0,利用了我所说的curiously powerful || operator。 (当undefined成为 fassy *值有效时,请注意执行此操作。)

在ES2015及更高版本中,您可以在参数列表中执行以下默认设置:

something

如果不为这些参数提供参数(或者为它们明确提供function Prod(price = 0, available = 0) { this.price = price; this.available = available; } ),则将应用默认值。

*“ falsy”-在JavaScript中,用作布尔值时强制为undefined的值为 falsy 。伪造的值是false0""nullundefined,当然还有NaN。所有其他值都是 truthy


几个旁注:

  1. 在JavaScript中,压倒性的约定是仅对构造函数使用初始加盖的名称,而不对引用其他内容的变量使用。因此falseprodStruct

  2. prods之类的一系列东西可能最好是数组(Prods),而不是具有编号属性的对象。

  3. 仅当名称不是有效的标识符或有效的整数时,才需要在对象初始值设定项中使用属性引号引起来。您所有的财产名称都是,所以您可以将其保留。

  4. 尽管[]可以工作,但是更简单,更习惯地写为Prods['6']['price']