从另一个对象更新 JavaScript 对象属性 [重复]
Posted
技术标签:
【中文标题】从另一个对象更新 JavaScript 对象属性 [重复]【英文标题】:Updating JavaScript object-attributes from another object [duplicate] 【发布时间】:2012-09-14 02:17:02 【问题描述】:我想更新一个看起来像这样的对象:
currentObject =
someValue : "value",
myObject :
attribute1 : "foo",
attribute2 : "bar"
;
.. 使用包含一些更改的对象,即:
updateObject =
myObject :
attribute2 : "hello world"
;
最后我想更新 currentObject 以便:
currentObject.myObject.attribute2 == "hello world"
这也应该适用于其他对象.. 作为一种解决方案,我考虑过迭代对象并以某种方式处理命名空间。但我想知道使用 jQuery 或原型之类的库是否有一个简单的解决方案。
【问题讨论】:
如果你使用 jQuery,$.extend
应该可以满足你的需求。
@RocketHazmat:不,它不是递归的。
@Bergi:如果您将true
作为第一个参数传递,那就是! ;-)
@Bergi 在您声明之前请先查一下。这是一个链接,您可以阅读有关.extend
的信息:api.jquery.com/jQuery.extend
@RocketHazmat:是的,我总是忘记这一点(我不太喜欢这个函数,因为它的数组处理)
【参考方案1】:
我建议使用 underscore.js(或者更好,lo-dash)extend:
_.extend(destination, *sources)
将源对象中的所有属性复制到 目标对象,并返回目标对象。 这是有序的, 所以最后一个源将覆盖同名的属性 以前的论点。
_.extend(name: 'moe', age: 50); => name: 'moe', age: 50
【讨论】:
据我所知,Underscore 和 Lodash 的extend
都将覆盖 myObject
属性,而不是简单地更新它(即它将包含 only @987654325 @)。但是,Lodash 的 merge
会起作用。
正如@TataBlack 所指出的,给定var a = name: 'moe', age: 50, b = age: 30; var c = _.merge(, a, b);
,c
将是name: 'moe', age: 30
,而a
和b
保持不变。【参考方案2】:
function update(obj/*, …*/)
for (var i=1; i<arguments.length; i++)
for (var prop in arguments[i])
var val = arguments[i][prop];
if (typeof val == "object") // this also applies to arrays or null!
update(obj[prop], val);
else
obj[prop] = val;
return obj;
应该可以解决问题:update(currentObject, updateObject)
。您可能想要添加一些类型检查,例如 Object(obj) === obj
以仅使用真实对象扩展真实对象,对数组使用正确的循环或 hasOwnProperty
测试。
【讨论】:
【参考方案3】:这是一个Object.keys
和递归示例:
// execute object update function
update(currentObject, updateObject)
// instantiate object update function
function update (targetObject, obj)
Object.keys(obj).forEach(function (key)
// delete property if set to undefined or null
if ( undefined === obj[key] || null === obj[key] )
delete targetObject[key]
// property value is object, so recurse
else if (
'object' === typeof obj[key]
&& !Array.isArray(obj[key])
)
// target property not object, overwrite with empty object
if (
!('object' === typeof targetObject[key]
&& !Array.isArray(targetObject[key]))
)
targetObject[key] =
// recurse
update(targetObject[key], obj[key])
// set target property to update property
else
targetObject[key] = obj[key]
)
JSFiddle demo(打开控制台)。
【讨论】:
【参考方案4】:一个简单的实现如下所示。
function copyInto(target /*, source1, sourcen */)
if (!target || typeof target !== "object")
target = ;
if (arguments.length < 2)
return target;
for (var len = arguments.length - 1; len > 0; len--)
cloneObject(arguments[len-1], arguments[len]);
return target;
function cloneObject(target, source)
if (!source || !target || typeof source !== "object" || typeof target !== "object")
throw new TypeError("Invalid argument");
for (var p in source)
if (source.hasOwnProperty(p))
if (source[p] && typeof source[p] === "object")
if (target[p] && typeof target[p] === "object")
cloneObject(target[p], source[p]);
else
target[p] = source[p];
else
target[p] = source[p];
这假定不应克隆任何继承的属性。它也不检查诸如 DOM 对象或盒装原语之类的东西。
我们需要对参数进行反向迭代,以便从右到左完成复制。
然后我们创建一个单独的cloneObject
函数来处理嵌套对象的递归复制,其方式不会干扰原始对象参数的从右到左复制。
它还确保初始目标是一个普通对象。
cloneObject
函数如果传递了一个非对象将抛出一个错误。
【讨论】:
为什么要从源到源再到……再到目标? @Bergi:我猜只是一种不同的方法,但我确实认为我应该通过创建临时对象而不是修改原始对象来使其成为非破坏性的。另外,如果有foo:[...] <- foo:...
的情况,我应该真正区分数组和对象。
是的,它对源应该是非破坏性的 - 但您不需要临时对象,只需 cloneInto(target)
。是的,用数组扩展普通对象很痛苦:-)以上是关于从另一个对象更新 JavaScript 对象属性 [重复]的主要内容,如果未能解决你的问题,请参考以下文章