Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/431.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript循环遍历对象,甚至在子对象中插入缺少的键_Javascript_Object_Nested - Fatal编程技术网

Javascript循环遍历对象,甚至在子对象中插入缺少的键

Javascript循环遍历对象,甚至在子对象中插入缺少的键,javascript,object,nested,Javascript,Object,Nested,我需要同步两个javascript对象,我想用object1中缺少的键填充object2,而不替换现有键,即使是嵌套键: var object1 = { firstName: "Marco", lastName: "Rossi", favoriteFood: {firstCourse: "pasta", secondCourse: "salsiccia"}, favoriteDrink: "Vino", favoriteSong: "O sole mio"

我需要同步两个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"
}

提前感谢您的帮助。

一种方法是检查
typeof()
每个对象属性并递归遍历。

您需要遍历整个对象,并询问键/值对的变量类型。如果它是一个物体,再做一次

for(var prop in object1){
    if(object1.hasOwnProperty(prop)){
        if(!(prop in object2)){
            object2[prop] = object1[prop];
        }
    }
}
这个例子很小


(我将不讨论这个问题,但Crossfires版本已经更快、更完整了)

您需要编写递归函数来处理嵌套对象。也许是这样的:

var object1={
名字:“马可”,
姓:“罗西”,
最喜欢的食物:{第一道菜:“意大利面”,第二道菜:“盐腌菜”},
favoriteMovie:{评级:7,标题:“星期一”},
最爱的饮料:“葡萄酒”,
最喜欢的歌曲:“哦,我的唯一”
}
var object2={
名字:“马可”,
姓:“罗西”,
最喜欢的食物:{第一道菜:“意大利面”},
最喜欢的歌曲:“维亚吉尔”
}
函数fillObject(从、到){
for(从中输入变量){
if(来自.hasOwnProperty(键)){
if(Object.prototype.toString.call(从[key])=='[Object Object]'){
如果(!to.hasOwnProperty(键)){
到[键]={};
}
fillObject(从[key],到[key]);
}
如果(!to.hasOwnProperty(键)){
到[键]=从[键];
}
}
}
}
fillObject(object1、object2);

警报(JSON.stringify(object2,null,)这对我很有效。我认为这很简单。只需检查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;
}

如果目标中的路径为null,所有这些答案都将失败,因此在递归之前,有必要深入查看对象1级,检查目标节点是否为null,如果是,则在递归之前更新它

注意:我的回答与其他人的观点顺序不同。a是要检查是否缺少关键帧的项,b是具有正确关键帧的引用对象。我的函数还返回true/false,以确定是否对a进行了任何更改。当缺少键时,它还会将默认值从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]

另一个问题的答案可能重复提到jQuery和非jQuery的方法,那么嵌套对象呢?我认为这对嵌套对象不起作用。如果两者都有相同的对象作为键,并且object2中缺少一些键,那么这段代码将不允许复制,因为:如果(!(object2中的prop))在彻底测试了这一点之后,有一种情况不起作用。如果嵌套键不存在,则不会创建它。假设object2中不存在favoriteFood,此代码不会在object1中创建一个。我还在努力理解为什么。当然!如果发现其他问题,请随时返回。如果预期对象为
null
,则此操作将失败。例如,如果
favoriteFood
为null,则它将保持
null
。如果有人知道修复方法,我将不胜感激。
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]