Je veux mettre à jour un objet qui pourrait ressembler à ceci:
currentObject = {
someValue : "value",
myObject : {
attribute1 : "foo",
attribute2 : "bar"
}
};
.. avec un objet contenant des modifications, à savoir:
updateObject = {
myObject : {
attribute2 : "hello world"
}
};
A la fin, j'aimerais que currentObject soit mis à jour de sorte que:
currentObject.myObject.attribute2 == "hello world"
Cela devrait également être possible pour d’autres objets. Comme solution, j’ai pensé à parcourir l’objet et à prendre en charge l’espace de noms. Mais je me demande s’il existe une solution facile à ce problème en utilisant une bibliothèque telle que jQuery ou prototype.
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;
}
devrait faire l'affaire: update(currentObject, updateObject)
. Vous voudrez peut-être ajouter des contrôles de type, tels que Object(obj) === obj
pour étendre uniquement les objets réels avec des objets réels, utilisez une boucle correcte pour les tableaux ou les tests hasOwnProperty
.
Je suggère d'utiliser underscore.js (ou mieux, lo-dash) extend :
_.extend (destination, * sources)
Copiez toutes les propriétés des objets source sur l'objet de destination Et renvoyez-les.il est dans l'ordre, De sorte que la dernière source remplacera les propriétés du même nom dans les arguments précédents de.
_.extend({name: 'moe'}, {age: 50}); => {name: 'moe', age: 50}
Une implémentation simple ressemblerait à ceci.
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];
}
Cela suppose qu'aucune propriété héritée ne doit être clonée. En outre, il ne vérifie pas des objets tels que les objets DOM ou les primitives en boîte.
Nous devons parcourir les arguments en sens inverse pour que la copie soit faite dans une matière de droite à gauche.
Ensuite, nous créons une fonction cloneObject
distincte pour gérer la copie récursive d'objets imbriqués de manière à ne pas interférer avec la copie de droite à gauche des arguments de l'objet d'origine.
Cela garantit également que la cible initiale est un objet simple.
La fonction cloneObject
émettra une erreur si un non-objet lui a été transmis.
Voici un exemple Object.keys
et récursif:
// 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]
}
})
}