You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NodeJS中嵌套对象内数组实例全部重复的问题排查

问题描述

我有一个嵌套对象数组,每个对象内部包含一个lines数组,简化结构如下:

const nestedArray = [ objectTemp{foo: "", lines: []} ] // 嵌套数组结构的简化示例

我给每个模板对象填充不同的foo值和lines数组内容,然后推入nestedArray。但操作后发现,nestedArray中每个对象的lines数组内容完全相同,而foo值则正常保持不同。

实际场景是遍历订单数据orderData,拆分客户与订单数据,combinedData是存储newOrder对象的数组,每个newOrder的lines数组用于存储订单项。循环结束后,每个对象的属性值都正常不同,但所有对象的lines数组内容完全一致。

以下是实际代码:

主循环代码

for(let i = 0; i < orderData.length; i++){
  if(lastOrder === orderData[i]["Order Name"]){
    // 多订单项的订单
    newLine = await fillLineData(orderData[i]);
    await pushToArray(newOrder.lines, newLine);
  }
  else{
    // 循环进入下一订单,将newOrder对象存入combinedData数组
    if(lastOrder) {
      await pushToArray(combinedData, newOrder);
      newOrder = await clearObject(newOrder);
    }

    // 开始处理下一订单数据
    const extKey =  await getCustomerKey(orderData[i]);
    newOrder = await fillCustomerData(orderData[i], extKey);
    newLine = await fillLineData(orderData[i]);
    await pushToArray(newOrder.lines, newLine);
  }

  lastOrder = orderData[i]["Order Name"];
} 
await pushToArray(combinedData, newOrder);

// 辅助函数
async function pushToArray(arr, obj){
  try{
    arr.push(obj);
  }catch(e){
    console.log("Failed to push order lines to array... Error: ", e);
  }
}

fillCustomerData函数代码

async function fillCustomerData(orderData, extKey){
  const newData = Object.create(orderCustomerData);

  newData.customer_name = orderData["Customer Name"];
  newData.shipto_name = orderData["Customer Name (Shipping)"];
  newData.shipto_address_1 = orderData["Shipping Address 1"];
  newData.shipto_address_2 = orderData["Shipping Address 2"];
  newData.shipto_city = orderData["Shipping City"];
  newData.shipto_state = orderData["Shipping Province Code"];
  newData.shipto_zip = orderData["Shipping ZIP"];
  newData.shipto_country = orderData["Shipping Country"],
  newData.billto_name = orderData["Customer Name (Billing)"];
  newData.billto_address_1 = orderData["Billing Address 1"];
  newData.billto_address_2 = orderData["Billing Address 2"];
  newData.billto_city = orderData["Billing City"];
  newData.billto_state = orderData["Billing Province Code"];
  newData.billto_zip = orderData["Billing ZIP"];
  newData.billto_country = orderData["Billing Country"];
  newData.po = orderData["Order Name"];
  newData.tax_collected = orderData["Total Tax"];
  newData.freight_resale = orderData["Shipping Price"];
  newData.external_key = extKey;
  return newData;
}

问题原因与解决方案

核心原因

你用Object.create(orderCustomerData)创建对象时,orderCustomerData里的lines数组是引用类型,会作为原型属性被所有newData实例共享。也就是说,所有newOrder对象的lines其实指向同一个数组地址,不管你给哪个对象的lines加元素,所有对象的lines都会同步变化,最终内容完全一致。

而foo这类基本类型属性,你在newData上直接赋值时,会在实例自身创建新属性覆盖原型上的同名属性,所以每个对象的foo值能保持独立。

解决方案

1. 修改fillCustomerData函数,给每个实例创建独立lines数组

在创建newData后,新增一行代码给当前实例单独初始化lines数组,切断原型共享:

async function fillCustomerData(orderData, extKey){
  const newData = Object.create(orderCustomerData);
  // 给当前实例创建独立的lines数组
  newData.lines = [];

  newData.customer_name = orderData["Customer Name"];
  newData.shipto_name = orderData["Customer Name (Shipping)"];
  // ...其他属性赋值代码保持不变
  return newData;
}

2. 检查clearObject函数的处理逻辑

如果clearObject只是清空原数组(比如用obj.lines.length = 0),会导致后续复用的对象仍然共享同一个数组。确保clearObject是给lines重新赋值新数组:

async function clearObject(obj) {
  // 清空其他属性...
  obj.lines = []; // 重置为新数组,而非清空原数组
  return obj;
}

这样每个newOrder对象都会拥有独立的lines数组,各自的订单项就不会互相干扰了。


内容的提问来源于stack exchange,提问作者NoahDuV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 05:12:07