首页 > 解决方案 > 在reduce的对象中设置一个特定键的属性就是为所有属性设置它

问题描述

好吧,我真的不知道这里发生了什么。我假设它是某种参考问题?但我不知道如何解决它或导致它的原因。

总而言之,我有一个对象列表,以及一个预先填充的对象,以确保我拥有对象中所有键的数据。

我需要遍历这个对象列表,并通过使用元数据对象中的 timeframeId 和数据对象中的 id,我想将整个数据对象分配给预填充对象中相应的 timeframeId 和 id 层次结构。

出于某种原因,所有data属性都被覆盖到最后一行data

我已经链接了一个 repl,所以您可以自己查看:https ://repl.it/@ThomasVermeers1/UnwrittenNoisyFirm#index.js

但我的代码如下:

const buildSegmentsFromRows = (rows, timeframeMetadata, defaultSegmentData) => {
  // Prepopulate object to make sure every timeframe has a 'hello' key in it with some data
  const emptySegments = timeframeMetadata.reduce((segmentMap, metadata) => {
    segmentMap[metadata.timeframeId] = {
      metadata,
      segments: defaultSegmentData,
    };
    return segmentMap;
  }, {});

  // Now simply just loop over the rows, and set [row.metadata.timeframeId].segments[row.data.id] to row.data
  const segments = rows.reduce((partialSegments, row) => {
    const { timeframeId } = row.metadata;
    const { id } = row.data;

    /**
     * This is the line where everything goes wrong
     */
    partialSegments[timeframeId].segments[id] = row.data;
    return partialSegments;
  }, emptySegments);
  return segments;
};

const rows = [
  {
    metadata: { timeframeId: '20202_01' },
    data: {
      'id': 'hello', 'value': 15
    }
  },
  {
    metadata: { timeframeId: '20202_02' },
    data: {
      'id': 'hello', 'value': 10
    }
  }
]

const timeframemetadata = [
  { timeframeId: '20202_01'},
  { timeframeId: '20202_02'}
]

const defaultSegmentData = {
  'hello': {
    'id': 'hello',
  }
}
console.log(JSON.stringify(buildSegmentsFromRows(rows, timeframemetadata, defaultSegmentData), null, 2))

我期待最终结果是:

{
  "20202_01": {
    "metadata": {
      "timeframeId": "20202_01"
    },
    "segments": {
      "hello": {
        "id": "hello",
        "value": 15
      }
    }
  },
  "20202_02": {
    "metadata": {
      "timeframeId": "20202_02"
    },
    "segments": {
      "hello": {
        "id": "hello",
        "value": 10
      }
    }
  }
}

但相反,在所有情况下都value设置为。10我在想它是因为我们将属性设置为row.data,这是一个参考,并且在每次调用时都会更新?但我在这里完全不知所措。

标签: javascriptnode.js

解决方案


问题是您为segments列表中的每个都引用了相同的对象。

因此,更改 的值segments[id]将更新defaultSegmentData,从而导致每个对 的引用也defaultSegmentData发生变化。

  const emptySegments = timeframeMetadata.reduce((segmentMap, metadata) => {
    segmentMap[metadata.timeframeId] = {
      metadata,
      segments: defaultSegmentData, // Everything goes wrong here.
    };
    return segmentMap;
  }, {});

此问题的一个简单解决方案是在创建时避免使用对对象的相同引用segmentMap

  const emptySegments = timeframeMetadata.reduce((segmentMap, metadata) => {
    segmentMap[metadata.timeframeId] = {
      metadata,
      /** Or whatever default value you want. 
      *   Just make sure to create a new instance of it for each call.
      */
      segments: {},
    };
    return segmentMap;
  }, {});

推荐阅读