我需要同步两个javascript对象,我想用object1中的缺失键填充object2而不替换现有的,即使是嵌套的:
var object1 = {
firstName: "Marco",
lastName: "Rossi",
favoriteFood: {firstCourse: "pasta", secondCourse: "salsiccia"},
favoriteDrink: "Vino",
favoriteSong: "O sole mio"
}
var object2 = {
firstName: "Marco",
lastName: "Rossi",
favoriteFood: {firstCourse: "pasta"},
favoriteSong: "Viaggiare"
}
我真的不知道如何进入嵌套键。特别是为了继续检查内巢,如果你有5个巢或类似的东西怎么办我知道如何处理第一级而不是进一步下降。
objec2的理想结果是
var object2 = {
firstName: "Marco",
lastName: "Rossi",
favoriteFood: {firstCourse: "pasta", secondCourse: "salsiccia"},
favoriteDrink: "Vino",
favoriteSong: "Viaggiare"
}
提前感谢您的帮助。
答案 0 :(得分:4)
您需要编写递归函数来处理嵌套对象。也许是这样的:
var object1 = {
firstName: "Marco",
lastName: "Rossi",
favoriteFood: {firstCourse: "pasta", secondCourse: "salsiccia"},
favoriteMovie: {rating: 7, title: "Monday"},
favoriteDrink: "Vino",
favoriteSong: "O sole mio"
}
var object2 = {
firstName: "Marco",
lastName: "Rossi",
favoriteFood: {firstCourse: "pasta"},
favoriteSong: "Viaggiare"
}
function fillObject(from, to) {
for (var key in from) {
if (from.hasOwnProperty(key)) {
if (Object.prototype.toString.call(from[key]) === '[object Object]') {
if (!to.hasOwnProperty(key)) {
to[key] = {};
}
fillObject(from[key], to[key]);
}
else if (!to.hasOwnProperty(key)) {
to[key] = from[key];
}
}
}
}
fillObject(object1, object2);
alert( JSON.stringify(object2, null, ' ') );
注意:如果您想知道这一行Object.prototype.toString.call(from[key])
- 这是为了可靠地检查该值是否为对象,因为typeof null
也报告object
。
答案 1 :(得分:1)
for(var prop in object1){
if(object1.hasOwnProperty(prop)){
if(!(prop in object2)){
object2[prop] = object1[prop];
}
}
}
答案 2 :(得分:1)
这对我有用。我觉得它非常简单。只需检查object2中是否存在属性,否则将其复制(如果它不是对象)。如果它是一个对象递归。
(function(){
console.log("EXECTURING");
var object1 = {
firstName: "Marco",
lastName: "Rossi",
favoriteFood: {firstCourse: "pasta", secondCourse: "salsiccia"},
favoriteDrink: "Vino",
favoriteSong: "O sole mio"
};
var object2 = {
firstName: "Marco",
lastName: "Rossi",
favoriteFood: {firstCourse: "pasta"},
favoriteSong: "Viaggiare"
};
for( key in object1) {
if(object1.hasOwnProperty(key)) {
copyToB(key, object1, object2);
}
}
})();
function copyToB(key, o1, o2) {
if(typeof(o1[key]) !== "object") {
if(typeof o2[key] === "undefined")
o2[key] = o1[key];
return;
}
var tempObj = o2[key];
for(k in o1[key]) {
copyToB(k, o1[key], tempObj);
}
o2[key] = tempObj;
}
答案 3 :(得分:0)
执行此操作的一种方法是检查typeof()
每个对象属性并以递归方式遍历。
答案 4 :(得分:0)
您需要浏览完整的对象并询问键/值对的变量类型。如果它是一个对象,请再次执行。
此fiddle中的迷你示例。
$.each(object1, function( index, value ) {
console.log( index + ": " + typeof(value) );
});
(我将离开,但Crossfires版本已经更快更完整了)
答案 5 :(得分:0)
function sync(source, target) {
if(getType(source) !== 'object' || getType(target) !== 'object') {
return;
}
for(var p in source) {
if(getType(target[p]) === 'object') {
if(getType(target[p]) !== 'object') {
target[p] = {};
}
sync(source[p], target[p]);
} else if(getType(target[p]) === 'null' || getType(target[p]) === 'undefined'){
target[p] = source[p];
}
}
};
function getType(arg) {
if(arg === null) {
return 'null';
} else if(arg === undefined) {
return 'undefined';
}
var type = Object.prototype.toString.call(arg);
return type.slice(8, type.indexOf(']')).toLowerCase();
};
答案 6 :(得分:0)
如果目标中的路径为null,则所有这些答案都将失败,因此有必要在递归之前向对象深1级查找,并检查目标节点是否为null,如果是,则在递归之前对其进行更新
注意:我的答案采用的论点顺序与其他人不同。 a是要检查缺少键的项目,b是具有正确键的参考对象。对于是否对a进行了任何更改,我的函数还返回true / false。还会在缺少键时将默认值从b复制到a。
function has (o,k) {
return typeof o==='object'&&(o.hasOwnProperty(k)||o[k]!==undefined);
}
function recursiveCheck( a, b ) {
var c = false;//whether we have changes. the calling scope wants to know
// a is the object to check, b is the target
for(let k in b) {
if(!has(a,k)) {
c=true;
a[k] = b[k];
}else{
// if b[k] is an object, we recursively check on the children for changes
// we only want to manipulate a[k] if b[k]=== object and not null!!!
if(typeof b[k]==='object'&&b[k]!==null){
for(let k2 in b[k]) {
if(a[k]===null){
a[k]=b[k];
c=true;
}
if( (!has(a[k],k2) || a[k][k2]===null) && typeof b[k][k2]==='object' && b[k][k2]!==null){
a[k][k2] = b[k][k2];
c=true;
}
}
const hasChange = recursiveCheck(a[k],b[k]);
c = c || hasChange;
}
}
}
return c;
}
用法
var a = { foo: null, bar: true };//this is the object we are checking
var b = { foo:{test:1,hello:false},bar: false}; //this is the object with correct keys and default values that should copy over to a when needed.
const didChange = recursiveCheck(a,b);
证明正确输出的测试用例
var target = {
private:{
has:false,
cost:0
},
shared:{
has:false,
cost:0
}
}
var inputs = [
{},// true
{private:null,shared:null},// true
{private:{has:true},shared:{cost:50}},// true
{private:{has:true,cost:500},shared:{has:false,cost:250}}// false
];
console.log('inputs---',inputs);
const results = inputs.map(item=>recursiveCheck(item,target));
console.log('inputs(transformed)---',inputs);
console.log('results---',results); // should be [true, true, true, false]