【问题标题】:How does this function create a nested object?此函数如何创建嵌套对象?
【发布时间】:2021-08-19 00:15:59
【问题描述】:

我一直在使用以下函数的一个版本来创建和/或向嵌套对象添加值:

    function assign(obj, keyPath, value) {
      const lastKeyIndex = keyPath.length-1;
       for (let i = 0; i < lastKeyIndex; ++ i) {
         const key = keyPath[i];
         if (!(key in obj)){
           obj[key] = {}
         }
         obj = obj[key];
       }
       obj[keyPath[lastKeyIndex]] = value;
    }

(由 kennytm 于 2011 年发表,以上稍作修改: Javascript: how to dynamically create nested objects using object names given by an array)。

指定值的示例用法,其中键表示 (0) 数据库 名称、(1) 表名、(3) id 值和(4) 列名:

    let obj = {}
    assign(obj, ['farm', 'products', '25', 'product_name'], 'lettuce');

    console.log(JSON.stringify(obj));
    /* (reformatted)
    {
      "farm": {
        "products": {
          "25": {
            "product_name":"lettuce"
          }
        }
      }
    } 
    */

我们可以为同一行添加第二个值:

    assign(obj, ['farm', 'products', '25', 'product_unit'], 'head');

    console.log(JSON.stringify(obj));
    /* (reformatted)
    {
      "farm": {
        "products": {
          "25": { 
            "product_name":"lettuce",
            "product_unit":"head"
          }
        }
      }
    }
    */

或来自不同行、表和数据库的附加值:

    assign(obj, ['farm', 'equipment', '17', 'equipment_name'], 'tractor');

    console.log(JSON.stringify(obj));
    /* (reformatted)
    {
      "farm": {
        "products": {
          "25": {
            "product_name": "lettuce",
            "product_unit": "head"
          }
        },
        "equipment": {
          "17": {
            "equipment_name": "tractor"
          }
        }
      }
    }
    */

该函数运行良好,但我不知道它是如何管理聚合关键路径的。它似乎只是用仅包含最后一个键和值的对象创建或替换现有对象。事实上,如果我不在函数内部且不使用循环执行相同的语句,这些语句就是这样做的。

(从将第一个值分配给空对象开始):

    let obj = {}
    let key;
    
    // first iteration of the function's loop
    key = 'farm';
    if (!(key in obj)) {
      obj[key] = {}
    }
    obj = obj[key];
    
    // second iteration
    key = 'products';
    if (!(key in obj)) {
      obj[key] = {}
    }
    obj = obj[key];
    
    // third iteration
    key = '25';
    if (!(key in obj)) {
      obj[key] = {}
    }
    obj = obj[key];
    
    // final line from the function
    obj['product name'] = 'lettuce';

    console.log(JSON.stringify(obj));
    // {"product name":"lettuce"}

如您所见,对象不是嵌套的,而是在每个步骤中简单地替换。

什么魔法使函数的工作方式不同?

【问题讨论】:

  • const myObj = {}; assign(myObj, ['farm', 'products', '25', 'product_name'], 'lettuce'); console.log(myObj) 开始可能会有所帮助 - 与函数参数 obj 命名不同。

标签: javascript function object


【解决方案1】:

不同之处在于您没有保存引用原始对象的变量。当您重新分配 obj 时,您不再拥有包含父级的变量。

使用函数时,该变量在函数调用者中。重新分配局部变量obj 对调用者的变量没有影响。

要在您的手动步骤中模拟这一点,请将开头更改为:

const original = {};
let obj = original;

这类似于函数参数的传递方式。

然后在最后,做

console.log(JSON.stringify(original));

您应该会看到添加了所有嵌套属性的整个对象。

【讨论】:

  • 谢谢你,Barmar 和 Bergi!我知道魔术与函数的对象参数成为对该对象的全局引用的副本有关。但我不能再进一步了。您的回答应该可以帮助我更好地理解如何处理函数中的对象。
  • 我赞扬你首先付出了所有努力。手动执行代码是了解其工作原理的最佳方式之一。我们有很多人只是发布代码并询问“请解释这段代码是如何工作的”。
猜你喜欢
  • 1970-01-01
  • 2021-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-02
  • 1970-01-01
  • 2019-10-06
  • 2014-01-10
相关资源
最近更新 更多