2012-08-31 120 views
1

可能重复:
Dynamic object property name串联访问的对象属性

我要动态地生成访问对象的属性。

如果我尝试访问mydata[i].val.name,我会得到somename

如果我尝试像mydata[i] + bar[j](其中bar [j] ==='.val.name')它失败。

我该如何动态创建这样的东西?这样我可以使用用户生成的值访问对象的任何属性?


一些代码:

如果我有一个对象我希望能够通过它的属性进行迭代,收集我感兴趣的是那些理想的情况下,我想类似如下:

var processData = function (data, keys, values) { 
    var returnData = [], i, j, k; 
    var parsedData = JSON.parse(data); 
    var keys = keys || null; 
    var values = values || null; 
    var datalen = parsedData.length; 

    for (i = 0; i < datalen; i++) { 
     returnData[i] = {}; 
     for(j = 0; j< keys.length; j++){ 
      for(k = 0; k < values.length; k++){ 
       returnData[i][keys[j]] = parsedData[i] + values; 
      } 
     } 
    } 

    return returnData; 
}; 

,然后用它喜欢:

var keys = ["foo","bar"]; 
var values = [".val.name", ".val.date"]; 
processData(data, keys, values); 

但是,这并不工作,并在CONSOL e我看到foo="[object Object].val.name"而不是预期的foo="ACME Industries"

+0

你可以发布你正在使用的对象的例子吗?我也会小心命名对象和参数相同,它只是看起来容易混淆,可能会导致问题。 – elclanrs

+0

^^同意。这个'mydata [i] + bar [j]'连接任何这些值。 – elclanrs

+0

我已经更新了我的答案,以便在问题结束时使用查询,并演示了它的工作原理。 –

回答

1

如果你要坚持你的构建标与它点的字符串,你必须推出自己的查找功能,像这样的模式:

function descend(object, sub) { 
    var handle = object, 
     stack = sub.split('.'), 
     history = [], 
     peek; 

    while (handle[stack[0]]) { 
     if (peek) { 
      history.push(peek); 
     } 
     peek = stack.shift(); 
     handle = handle[peek]; 
    } 

    if (stack.length > 0) { 
     history.push(peek); 
     throw "Traversal error, could not descend to '" + stack.join('.') + "' from '" + history.join('.') + "'."; 
    } 

    return handle; 
} 

var x = { 
    a: { 
     b: { 
      c: 15 
     }, 
     d: 4 
    } 
}; 

console.log(descend(x, "a")); 
console.log(descend(x, "a.b")); 
console.log(descend(x, "a.b.c")); 
console.log(descend(x, "a.d")); 

function processData(data, keys, values) { 
    if (keys.length !== values.length) { 
     throw "Mismatched keys and value lookups"; 
    } 

    var i, 
     len = keys.length, 
     gathered = {}, 
     k, 
     scratch, 
     v; 

    for (i = 0; i < len; i += 1) { 
     k = descend(data, keys[i]); 
     scratch = values[i].split('.'); 
     scratch.shift(); 
     v = descend(k, scratch.join('.')); 
     gathered[keys[i]] = v; 
    } 

    return gathered; 
} 

var data = { 
    foo: { 
     val: { 
      name: "ACME Industries" 
     } 
    }, 
    bar: { 
     val: { 
      date: (new Date()) 
     } 
    } 
}; 
var keys = ["foo","bar"]; 
var values = [".val.name", ".val.date"]; 
processData(data, keys, values); 

请注意:这不会是近作为没有这种查找风格的编码的表现。

+0

已添加:未经测试的processData()函数 –

+0

经过测试的processData()函数 –

+0

如果此类查找不是高性能的,那么样式是什么? – Lothar

1

如果你尝试:

new Object() + '.john.doe' 

它将串联为一个字符串,所以你会得到"[object Object].john.doe"

您应该创建一个可以处理动态属性名称的函数(并且有很多这样的函数)。您也可能想将".foo.bar"语法作为一个字符串(除非您计划使用eval())并且仅使用数组来处理。

0

如果我理解正确的话,你需要使用

mydata[i]["val"]["name"] 

所以,我会使用这样的:

var result =getItemByValuesPath(myData[i],values); 
alert(result); 

function getItemByValuesPath(item, values) 
{ 
    var result = item; 

    var vals = values.split("."); 
    for(var j=0; j<values.length; j++) 
    { 
     if(result==undefined) 
      { 
        return null; 
      } 
    result = result[values[j]]; 
    } 
}