【问题标题】:Javascript object when setting property all properties with same name are set设置属性时设置所有同名属性的Javascript对象
【发布时间】:2018-12-02 14:31:38
【问题描述】:

我最近才开始使用 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);

输出:

{ '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 } }

【问题讨论】:

    标签: javascript node.js object


    【解决方案1】:

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

    +−−−−−−−−−−−−−−−+ 产品结构−−−−−−−−−−−−−−−+−+−+−+−+−+−+−−>| (对象) | / / / / / / / +−−−−−−−−−−−−−−−+ | | | | | | | |价格:0 | | | | | | | | |可用:0 | | | | | | | | +−−−−−−−−−−−−−−−+ +−−−−−−−−−−−+ | | | | | | | 产品----->| (对象) | | | | | | | | +−−−−−−−−−−−+ | | | | | | | | 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 来使用0 而不是undefined,利用我所说的curiously powerful || operator。 (当 something 是一个 falsy* 值有效时,请注意这样做。)

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

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

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

    * "falsy" - 在 JavaScript 中,当用作布尔值时强制转换为 false 的值是 falsy。虚假值为0""nullundefinedNaN,当然还有false。所有其他值都是truthy


    一些旁注:

    1. 在 JavaScript 中,压倒性的约定是只对构造函数使用初始封顶名称,而不是引用其他事物的变量。所以prodStructprods

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

    3. 仅当名称不是有效标识符或有效整数时,对象初始化程序中的属性名称才需要引号。您所有的属性名称都是,因此您可以不使用它们。

    4. 虽然Prods['6']['price'] 有效,但prods[6].price 写得更简单、更惯用。

    【讨论】:

    • op 应该有 20 个属性 ... ;-)
    • @NinaScholz - 哈哈,我会用... :-)
    • 感谢您的回答,所以要解决这个问题,我必须手动设置每个产品吗?
    • 不,您可以稍微更改一下 TJ 的功能,让您可以轻松地创建产品。 function Prod(price, available) { this.price = price, this.available = available} 然后创建一个新产品你可以做 new Prod(56.5, 500)
    猜你喜欢
    • 2013-04-11
    • 2021-10-08
    • 2015-03-14
    • 2019-04-23
    • 2019-07-20
    • 1970-01-01
    • 2018-10-19
    • 1970-01-01
    • 2018-06-05
    相关资源
    最近更新 更多