Javascript 生成一个函数,该函数接受一个对象、路径和值,并返回一个新对象,该对象的值位于path
注意:Object.assign将不起作用,因为它只生成浅拷贝 查看Ramda.js的源代码 我希望编写一个简单的函数,它将获取一个对象、一条路径和一个值,并返回一个新对象。理想情况下,新副本应尽可能有效 假设我有一个任意的对象,它可能是Javascript 生成一个函数,该函数接受一个对象、路径和值,并返回一个新对象,该对象的值位于path,javascript,object,Javascript,Object,注意:Object.assign将不起作用,因为它只生成浅拷贝 查看Ramda.js的源代码 我希望编写一个简单的函数,它将获取一个对象、一条路径和一个值,并返回一个新对象。理想情况下,新副本应尽可能有效 假设我有一个任意的对象,它可能是 const obj = { a: { b: { c: 1 } } e: 4 } 函数生成的结果示例 const obj2 = func(obj,['a','b','c'],99) console.log(obj
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
//}
理想的解决方案是高效地创建一个新对象,如下所示:
因此,如果
obj2.e=5
,则obj.e===5
,因为只有func
创建了正在修改的分支的副本,但保留了所有其他引用。可以使用reduce()
方法执行此操作
const obj={“a”:{“b”:{“c”:1}}
函数func(o,arr,val){
返回arr.reduce(函数(r,e,i){
返回arr[i+1]?(r[e]| |{}):r[e]=val
},o),o
}
const result=func(obj,['a','b','c'],99)
console.log(result)
调整@NenadVracar answer以处理缺少现有属性的边缘情况并创建新对象:
您可以首先克隆对象,然后根据需要使用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}}
请注意,该函数返回的是相同的修改对象,而不是新对象。很抱歉,这不提供原始对象的新副本。您正在将相同的对象传递到reduce中,而reduce进入了
func
,并且变异发生在相同的对象上。@nenadvrac喜欢使用逗号运算符。我花了一段时间才弄明白这是怎么回事@Babak,您可以使用对象。分配
从给定对象创建新对象理想情况下,解决方案将通过创建一个新对象,其中所有节点都引用原始对象,除了发生突变的地方,参考视频@Babak已使用对象进行编辑。分配
,或者,JSON.parse
和JSON.stringify
的组合。这些方法中的任何一种都应该保持不变性。希望有帮助!祝你好运嘿,谢谢你的回答,我们在讨论的早期讨论过这个问题,但是效率很低。@Babak我明白了。这也适用于Object.assign。祝你好运希望您能找到您正在查找的内容补充说明,JSON.parse/JSON.stringify将说明句柄Date
和值未定义的字段