2016-01-22 61 views
1

给定一个Javascript对象,如何遍历每个属性并获取每个节点的完全限定名称?我想这样的事情:获取当前JSON节点的完全限定名称

var test = { 
    "axes" : [{ 
     "stackType": "100%", 
     "testObject": { 
      "testProperty": "found" 
     }, 
     "minimum": 0 
    }, { 
     "gridColor": "#test", 
     "testArray": [ 
      {"jelly": 2}, {"jam": 3} 
     ], 
     "gridAlpha": 1 
    }] 
}; 

iterate(test); 

function iterate(obj, parents) { 

    if(!parents) { var parents = []; } 

    for (var property in obj) { 

     parents.push(property); 

     if (obj.hasOwnProperty(property)) { 

      if (typeof obj[property] == "object") { 
       iterate(obj[property], parents); 
      } 
      else if (obj[property].constructor == Array) { 
       for (var i = 0; i < obj[property].length; i++) { 
        iterate(obj[property][i], parents); 
       } 
      } 
      else { 
       console.log(parents + " : " + obj[property]); 
      } 

     } 

    } 

} 

但父母数组只是不断增加。我认为这是因为Javascript通过引用而不是按值来处理数组。

我所需的输出会是这样的:

axes, 0, stackType : 100% 
axes, 0, testObject, testProperty : found 
axes, 0, minimum : 0 
axes, 1, gridColor: #test 
axes, 1, testArray, 0, jelly: 2 
axes, 1, testArray, 1, jam: 3 
axes, 1, gridAlpha: 1 

而是我刚刚结束了与每一个新的属性,并将名单永不复位。

回答

3

在你的循环中,你需要创建一个在parents数组中传入的副本并附加property给它,并在递归调用中传递它。否则,你只是修改相同的数组。

var test = { 
 
    "axes": [{ 
 
    "stackType": "100%", 
 
    "testObject": { 
 
     "testProperty": "found" 
 
    }, 
 
    "minimum": 0 
 
    }, { 
 
    "gridColor": "#test", 
 
    "testArray": [{ 
 
     "jelly": 2 
 
    }, { 
 
     "jam": 3 
 
    }], 
 
    "gridAlpha": 1 
 
    }] 
 
}; 
 

 
iterate(test); 
 

 
function iterate(obj, parents) { 
 

 
    if (!parents) { 
 
    var parents = []; 
 
    } 
 

 
    for (var property in obj) { 
 

 
    // changed line: 
 
    var path = [].concat(parents, property); 
 

 
    if (obj.hasOwnProperty(property)) { 
 

 
     if (typeof obj[property] == "object") { 
 
     iterate(obj[property], path); // changed 
 
     } else if (obj[property].constructor == Array) { 
 
     for (var i = 0; i < obj[property].length; i++) { 
 
      iterate(obj[property][i], path); // changed 
 
     } 
 
     } else { 
 
     // changed so you can see it without opening the console 
 
     logLine(path.join(', ') + " : " + obj[property]); 
 
     } 
 

 
    } 
 

 
    } 
 
} 
 

 
function logLine(line) { 
 
    // show in console and in HTML 
 
    console.log(line); 
 
    document.getElementById('output').textContent += line + '\n'; 
 
}
<pre id="output"></pre>

+0

嘿,谢谢。这很好。我尝试了类似的东西,但我认为我的问题是将缓冲区变量(路径)放在for循环之外。 这也不是我需要的解决方案,因为我问了错误的问题。如果我给了你上下文(我需要合并两个对象),你可能会告诉我可以保存迭代并使用jQuery的$ .extend,如下所示: $ .extend(true,object1,object2); 与真正的合并递归。我将此标记为答案,但是为了防止有人发现这个答案试图解决我所遇到的同样问题,请将其作为答案。 –