【问题标题】:Produce a function that takes an object, path, and value and returns a new object with the value at path生成一个函数,该函数接受一个对象、路径和值,并返回一个新对象,该对象的值位于路径
【发布时间】:2018-01-29 09:52:23
【问题描述】:

注意:Object.assign 将不起作用,因为它只会进行浅拷贝。

查看 Ramda.js 的源代码

https://github.com/ramda/ramda/blob/v0.25.0/source/set.js

我正在寻找一个简单的函数,它将接受一个对象、一个路径和一个值并返回一个 new 对象。理想情况下,新副本尽可能高效。

https://www.youtube.com/watch?v=n5REbbvRYqQ&feature=youtu.be&t=15m3s

假设我有一个任意对象,可能是这个

const obj = {
  a: {
    b: {
       c: 1
    }
  }
  e: 4
}

函数产生的结果示例

const obj2 = func(obj,['a','b','c'],99)

console.log(obj2)
// {
//  a: {
//    b: {
//       c: 99
//    }
//  }
//  e: 4
//}

console.log(obj)
// {
//  a: {
//    b: {
//       c: 1
//    }
//  }
//  e: 4
//}

理想的解决方案是高效地创建一个新对象:https://www.youtube.com/watch?v=n5REbbvRYqQ&feature=youtu.be&t=15m3s

因此如果obj2.e = 5obj.e === 5 因为只有func 创建了正在修改的分支的副本,但保留了所有其他引用。

【问题讨论】:

    标签: javascript object


    【解决方案1】:

    调整@NenadVracar 答案以处理缺少预先存在的属性的边缘情况并创建一个新对象:

    您可以先克隆对象,然后根据需要使用reduce归结一个数组来构建路径。

    function func(o, arr, val) {
        var copyObj = JSON.parse(JSON.stringify(o));
        //OR
        //var copyObj = Object.assign({},o);
        return arr.reduce(function (r, e, i) {
            return arr[i + 1] ? (r[e] || (r[e] = {})) : r[e] = val
        }, copyObj), copyObj
    }
    

    我的测试用例:

    func({},['b','c'],4)  // {"b":{"c":4}}
    func({a:1},['b','c'],4)  // {"a":1,"b":{"c":4}}
    func({a:1,b:{d:5}},['b','c'],4)  //{"a":1,"b":{"d":5,"c":4}}
    func({a:1,b:{d:5,c:10}},['b','c'],4) //{"a":1,"b":{"d":5,"c":4}}
    

    【讨论】:

    • 嘿,谢谢你的回答,我们在讨论的早期就讨论过这个问题,但是效率很低。
    • @Babak 我明白了。这也适用于 Object.assign 。祝你好运。希望你能找到你要找的东西
    • 附加说明,JSON.parse / JSON.stringify 将记录句柄Date 和值为undefined 的字段
    【解决方案2】:

    您可以使用reduce() 方法来做到这一点。

    const obj = {"a":{"b":{"c":1}}}
    
    function func(o, arr, val) {
      return arr.reduce(function(r, e, i) {
        return arr[i+1] ? (r[e] || {}) : r[e] = val
      }, o), o
    }
    
    const result = func(obj, ['a','b','c'], 99)
    console.log(result)

    【讨论】:

    • 请注意,该函数返回相同的修改对象,而不是新对象。
    • 抱歉,这不提供原始对象的新副本。您将同一个对象传递给进入func 的reduce,并且突变发生在同一个对象上。
    • @NenadVracar 喜欢使用逗号运算符。我花了一段时间才弄清楚这是如何工作的。 @Babak,您可以使用 Object.assign 从给定的对象创建一个新对象
    • 理想情况下,解决方案将通过创建一个新对象,其中所有节点都引用原始对象,但发生突变的地方除外,视频供参考youtu.be/n5REbbvRYqQ?t=15m3s
    • @Babak 使用Object.assign 进行了编辑,或者使用了JSON.parseJSON.stringify 的组合。这些方法中的任何一个都应该保持不变性。希望能帮助到你!祝你好运!
    猜你喜欢
    • 2017-09-10
    • 2023-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-13
    • 1970-01-01
    相关资源
    最近更新 更多