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

Mr_*_*mes 0 javascript object node.js

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

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);
Run Code Online (Sandbox Code Playgroud)

输出:

{ '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 } }
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 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);
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper {
  max-height: 100% !important;
}
Run Code Online (Sandbox Code Playgroud)

...但我觉得在你的情况下我可能只有一个构造函数:

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);
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper {
  max-height: 100% !important;
}
Run Code Online (Sandbox Code Playgroud)

正如Rick在评论中提到的那样,你可以让构造函数接受参数:

function Prod(price, available) {
  this.price = price || 0;
  this.available = available || 0;
}
Run Code Online (Sandbox Code Playgroud)

在那里,如果你不提供priceavailable,它将具有价值undefined,并且该代码使用常用的习语something || default0代替undefined,使用我称之为奇怪的强大||操作符.(当它something是一个有价值的*值时,要小心这样做.)

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

function Prod(price = 0, available = 0) {
  this.price = price;
  this.available = available;
}
Run Code Online (Sandbox Code Playgroud)

如果您不为这些参数提供参数(或者您明确提供参数),则将应用默认值undefined.

*"falsy" - 在JavaScript中,false当用作布尔值时强制使用的值是假的.该falsy值0,"",null,undefined,NaN,当然,false.所有其他值都是真实的.


几个旁注:

  1. 在JavaScript中,压倒性的约定是仅对构造函数使用初始上限名称,而不是引用其他内容的变量.所以prodStructprods.

  2. 像你Prods这样的一系列东西可能会更好地作为一个数组([]),而不是一个具有数字命名属性的对象.

  3. 仅当名称不是有效标识符或有效整数时,才需要在对象初始值设定项中的属性名称周围引用.您的所有属性名称都是,所以您可以将它们关闭.

  4. 尽管Prods['6']['price']有效,但它更简单,更具有惯用语prods[6].price.