Aquí hay una solución parcial e ingenua a mi problema. Lo actualizaré a medida que lo desarrolle.
function findDifferences(objectA, objectB) {
var propertyChanges = [];
var objectGraphPath = ["this"];
(function(a, b) {
if(a.constructor == Array) {
// BIG assumptions here: That both arrays are same length, that
// the members of those arrays are _essentially_ the same, and
// that those array members are in the same order...
for(var i = 0; i < a.length; i++) {
objectGraphPath.push("[" + i.toString() + "]");
arguments.callee(a[i], b[i]);
objectGraphPath.pop();
}
} else if(a.constructor == Object || (a.constructor != Number &&
a.constructor != String && a.constructor != Date &&
a.constructor != RegExp && a.constructor != Function &&
a.constructor != Boolean)) {
// we can safely assume that the objects have the
// same property lists, else why compare them?
for(var property in a) {
objectGraphPath.push(("." + property));
if(a[property].constructor != Function) {
arguments.callee(a[property], b[property]);
}
objectGraphPath.pop();
}
} else if(a.constructor != Function) { // filter out functions
if(a != b) {
propertyChanges.push({ "Property": objectGraphPath.join(""), "ObjectA": a, "ObjectB": b });
}
}
})(objectA, objectB);
return propertyChanges;
}
Y aquí es una muestra de cómo se puede utilizar y los datos que proporcionaría (disculpen el largo ejemplo, pero quiero usar algo relativamente no trivial):
var person1 = {
FirstName : "John",
LastName : "Doh",
Age : 30,
EMailAddresses : [
"[email protected]",
"[email protected]"
],
Children : [
{
FirstName : "Sara",
LastName : "Doe",
Age : 2
}, {
FirstName : "Beth",
LastName : "Doe",
Age : 5
}
]
};
var person2 = {
FirstName : "John",
LastName : "Doe",
Age : 33,
EMailAddresses : [
"[email protected]",
"[email protected]"
],
Children : [
{
FirstName : "Sara",
LastName : "Doe",
Age : 3
}, {
FirstName : "Bethany",
LastName : "Doe",
Age : 5
}
]
};
var differences = findDifferences(person1, person2);
en este punto, esto es lo que la matriz differences
se vería como si serializado a JSON:
[
{
"Property":"this.LastName",
"ObjectA":"Doh",
"ObjectB":"Doe"
}, {
"Property":"this.Age",
"ObjectA":30,
"ObjectB":33
}, {
"Property":"this.EMailAddresses[1]",
"ObjectA":"[email protected]",
"ObjectB":"[email protected]"
}, {
"Property":"this.Children[0].Age",
"ObjectA":2,
"ObjectB":3
}, {
"Property":"this.Children[1].FirstName",
"ObjectA":"Beth",
"ObjectB":"Bethany"
}
]
el this
en el Property
valor se refiere a la raíz del objeto que se comparó. Por lo tanto, esta solución aún no es exactamente lo que necesito, pero está bastante cerca.
Espero que esto sea útil para alguien, y si tiene alguna sugerencia para mejorar, soy todo oídos; Escribí esto muy tarde anoche (es decir, temprano esta mañana) y puede haber cosas que estoy pasando por alto por completo.
Gracias.
Jason, gracias por su apoyo. Sin embargo, voy a eliminar mi respuesta. Obviamente, no es lo que buscabas después, y la implementación es discutible, así que supongo que no tiene sentido mantenerlo. Si tiene una solución que se adapte a sus necesidades, estaría interesado en verla aquí. – Tomalak
Estoy decepcionado de que haya decidido eliminarlo, pero respete su derecho a hacerlo. Simplemente he aprendido que hay cosas que se pueden aprender de las soluciones de los demás a los problemas, incluso si no resuelven el problema exacto para el que fueron diseñados. Podemos aprender de casi cualquier cosa. –