按 javascript 中的路径更新嵌套对象

Updating nested object by path in javascript

假设我有这个对象:

{
  categories: [
     { name: "My Category", products: [ { name: "My Product", price: 15 }] },
     { name: "Another", products: [ { name: "Movie", price: 25 }, { name: "Cartoon", price: 7.5 } ] },
     { name: "Lastly", subcategories: [ 
            { name: "Food", products: [ { name: "Avocado", price: 1.25} ] }
         ] 
     }
  ]
}

我希望能够通过如下函数调用更新此对象中的价格:

update(object, "categories/0/products/0",25) 
// this would change first product in first category

这个答案Javascript: how to dynamically create nested objects using object names given by an array很好,但没有解决对象中有数组的情况。

可接受下划线。

注意:这个答案 Javascript: how to dynamically create nested objects INCLUDING ARRAYS using object names given by an array 没有删减它,因为我没有那种形式的数组引用 (products[1])

您需要根据链接的答案稍微修改函数

var object = {
  categories: [
     { name: "My Category", products: [ { name: "My Product", price: 15 }] },
     { name: "Another", products: [ { name: "Movie", price: 25 }, { name: "Cartoon", price: 7.5 } ] },
     { name: "Lastly", subcategories: [ 
            { name: "Food", products: [ { name: "Avocado", price: 1.25} ] }
         ] 
     }
  ]
}

function update(obj, keyPath, value) {
   keyPath = keyPath.split('/');  // split key path string
   lastKeyIndex = keyPath.length-1;
   for (var i = 0; i < lastKeyIndex; ++ i) {
     key = keyPath[i];
     
     // choose if nested object is array or hash based on if key is number
     if (!(key in obj)) obj[key] = parseInt(key) !== parseInt(key) ? {}: []
     obj = obj[key];
   }
   obj[keyPath[lastKeyIndex]] = value;
}

console.log(`Original price ${object.categories[0].products[0].price}`);
update(object, "categories/0/products/0/price",25)
console.log(`New price ${object.categories[0].products[0].price}`);

我这样做了,也许它能帮到你。

const updateObjectValueByPath = ({ arrayPath, data, value }) => {
  const key = arrayPath[0];

  if (Array.isArray(data) && data !== null) {
    if (arrayPath.length > 1) {
      return data.map((el, index) => {
        if (index === key) {
          return updateObjectValueByPath({
            arrayPath: arrayPath.slice(1, arrayPath.length),
            data: el,
            value,
          });
        }

        return el;
      }, []);
    }

    return [...data, value];
  }

  if (typeof data === 'object' && !Array.isArray(data) && data !== null) {
    if (arrayPath.length > 1) {
      return {
        ...data,
        [key]: updateObjectValueByPath({
          arrayPath: arrayPath.slice(1, arrayPath.length),
          data: data[key],
          value,
        }),
      };
    }

    return { ...data, [key]: value };
  }

  return data;
};

const data = {
  categories: [
     { name: "My Category", products: [ { name: "My Product", price: 15 }] },
     { name: "Another", products: [ { name: "Movie", price: 25 }, { name: "Cartoon", price: 7.5 } ] },
     { name: "Lastly", subcategories: [ 
            { name: "Food", products: [ { name: "Avocado", price: 1.25} ] }
         ] 
     }
  ]
};

const arrayPath = ['categories', 0, 'products', 0, 'price'];
const value = 25;

const newData = updateObjectValueByPath({data, value, arrayPath});
console.log({newData});