我应该想要展平一个对象,为此我使用这个函数:
var flatter = function(ob){
var f = {};
for(var i in ob) {
if(typeof ob[i] == 'object') {
var newOb = flatter(ob[i]);
for(var x in newOb) {
f[i+'.'+x] = newOb[x];
}
}else{
f[i] = ob[i];
}
}
return f;
}
工作正常。我得到了适当的结果来应用这个对象:
var ob = {
"address" : {
"details" : {
"first" : "siva",
"last" : "sankara",
"mam":["mam1","mam2"]
}
}
};
结果是:
reslut : Object {address.details.first: "siva", address.details.last: "sankara", address.details.mam.0: "mam1", address.details.mam.1: "mam2"}
但是我无法理解我得到的结果。我理解,这是以recursion
和closure scope
为导向的 - 但是搜索谷歌我没有得到任何明确的教程或文章。
有人帮我逐步理解这一点吗?
提前致谢!
答案 0 :(得分:1)
function flatter(ob){
'use strict';
var f = {}, //return this
key;
for(key in ob) { //for each key
if (ob.hasOwnProperty(key)) {
if(typeof ob[key] === 'object') { //if value is object
//flatten this object again. Assign result to newOb
var newOb = flatter(ob[key]);
for(var x in newOb) {
f[key + '.' + x] = newOb[x];
}
} else {
f[key] = ob[key];
}
}
}
return f;
}
你可以用这样的代码翻译这段代码
function flatter(ob){
'use strict';
var f = {}, //return this object
key;
for(key in ob) { //for each key
if (ob.hasOwnProperty(key)) {
if(typeof ob[key] === 'object') { //if value is object
var newOb = (function (ob) {
'use strict';
var f = {}, //return this object
key;
for(key in ob) { //for each key
if (ob.hasOwnProperty(key)) {
if(typeof ob[key] === 'object') { //if value is object
var newOb = flatter(ob[key]);
for(var x in newOb) {
f[key + '.' + x] = newOb[x];
}
} else {
f[key] = ob[key];
}
}
}
return f;
}(ob[key]));
for(var x in newOb) {
f[key + '.' + x] = newOb[x];
}
} else {
f[key] = ob[key];
}
}
}
return f;
}
主要思想是每个函数调用都可以被这个函数的主体代替 对象本身是一个递归结构,因为它可以是内容对象。如果给出
{
id: 12345,
name: 'John',
friends: [12346, 75645, 96768]
}
不需要递归。对象不包含任何对象,因此它可以在没有附加函数调用的情况下被绑定(顺便说一下它是平的)。如果给出
{
id: 12345,
name: {
first: 'John',
last: 'Doe'
},
friends: [12346, 75645, 96768]
}
然后对象包含对象作为字段。所以你可以使用函数flatter,其中函数调用被函数体代替。如果给出
{
id: 12345,
name: {
first: 'Helen',
last: {
beforeMarriage: 'Dobsky',
afterMarriage: 'Bobsky'
}
},
friends: [12346, 75645, 96768]
}
然后一个人离不开3个函数调用。所以你可以复制三次函数体。但是,对象可以具有[无限]非常深的结构。所以函数的嵌套体的数量是未知的。因此,不是将函数体嵌套到函数中,而是使用递归调用 递归函数应至少有一个退出点以避免无限递归
return f;
在我们的案例中。可以到达此出口点,因为对象中的字段数是有限的。这不是解决任务的唯一方法。对象看起来像树(一种)递归可以用栈代替,它保留了复杂的字段,在处理完简单字段后返回到对象堆栈并在循环中处理它们。
堆栈实现。不漂亮,但有效)
function iflatter(input) {
'use strict';
var f = {}, //return this object
key,
stack = [],
ob,
prefix,
name;
stack.push(["", input]);
while (stack.length != 0) {
[prefix, ob] = stack.pop();
for(key in ob) { //for each key
if (ob.hasOwnProperty(key)) {
if (prefix !== "") {
name = prefix + "." + key;
} else {
name = key;
}
if(typeof ob[key] === 'object') {
stack.push([name, ob[key]]);
} else {
f[name] = ob[key];
}
}
}
}
return f;
}
答案 1 :(得分:0)
您正在将对象传递给flatter()
。当Object具有一个具有Object本身值的属性时,它会再次将该Object传递给flatter()
,或者递归传递。见if(typeof ob[i] == 'object')
?这意味着如果ob
具有属性i
并且其值(得到ob[i]
)是一个对象。注意var flatter = function(){}
相当于function flatter(){}
。