2013-02-07 57 views
1

设置嵌套对象的值,我想知道什么是更新多对象集合的成员在JavaScriptJavaScript的:通过ID

这里最好的办法是我收集的简化版本:

this.Steps = [ 

{ id: 1, text: "test", childSteps: 
    [ 
    { id: 2, text: "test"}, 
    { id: 3, text: "test"}, 
    { id: 4, text: "test", childSteps: 
    [ 
      { id: 10, text: "test"}, 
      { id: 11, text: "test"} 
    ]} 
    }, 
    { id: 5, text: "test"}, 
    { id: 6, text: "test"}, 
    { id: 7, text: "test"},  
    { id: 8, text: "test"}, 
    { id: 9, text: "test"} 
    ] 
} 
]; 

理想的做法是有一个函数被调用,如:

updateObjectByID(11, 'string to be set'); 

这是很容易的时候,我们只有1级对象的工作要做。但是当在多级集合上使用递归时,它变得更加困难。

我目前使用的是分析整个收集和建筑物串像一个功能:

this.Steps[0].childSteps[3].childSteps[1].text == "string to be set" 

,然后我该字符串做eval()

我敢肯定,可能有更清洁的解决方案。

使用eval使我的课无法压缩顺便说一句。

任何帮助将不胜感激。

在此先感谢

+0

“*解析整个集合*”...然后在这之后仍然必须使用'eval'?不能相信,请告诉我们该代码。 – Bergi

+0

Infact解析整个集合和构建字符串以更新集合成员。 – Tigoes

+0

如果我改变对象参数,它只会改变对象的引用,而不会改变我的集合,因为当做递归时,我会发送childSteps作为参考。 – Tigoes

回答

2

您可以通过ID直接访问地图上标注的对象:

var map = {}; 
(function recurse(steps) { 
    for (var i=0; i<steps.length; i++) { 
     var step = steps[i]; 
     map[ step.id ] = step; 
     if ("childSteps" in step) 
      recurse(step.childSteps); 
    } 
})(this.Steps); 

function updateObjectByID(id, string) { 
    map[id].text = string; 
} 

你的代码中的注释:你overcomplified很多。当满足条件if(obj.id == objId)时,您已经获得obj参考值!现在完全不需要搜索它的路径,从中创建一个字符串,并对其进行评估。直接分配给它的财产!

function(steps, objId, value, whatParam, command) { 
    if (typeof whatParam == 'undefined') 
     whatParam = 'selected'; 
    $.each(steps, function(index, obj){ 
     if(obj.id == objId) { 
      // removed a lot of unecessary stuff 

      // not sure, looks like "value" was evaled sometimes as well 
      obj[whatParam] = value; 

     } // insert an "else" here if ids are unique 
     if (typeof obj.childSteps != 'undefined') {   
      this.setupObjectState(obj.childSteps, objId, value, whatParam, command); 
     } 
    }); 
} 
+0

woow这一个作品:)。但我真的不知道如何!?!无论如何,非常感谢你的帮助! – Tigoes

+0

它们只是引用“Steps”数组中的完全相同的对象。 – Bergi

+0

关于简化版本...该功能正在做很多其他的事情,然后只是更新一个对象。它正在管理冲突的步骤(如果你选择一个,则取消选择另一个等等)。有时需要在实际找到对象之前撤消该命令。我知道这个解决方案是非常丑陋和低效的,但现在对于上面的解决方案,它将像医院一样干净。 – Tigoes

0

由于您使用ID调用updateObjectById(),因此ID必须是唯一的。为什么难道你不改变你的结构是这样,那么:

this.Steps = [ 
    { id: 1, text: "test" }, 
    { id: 2, parent: 1, text: "test" }, 
    { id: 3, parent: 1, text: "test" }, 
    { id: 4, parent: 1, text: "test" }, 
    { id: 10, parent: 4, text: "test" }, 
    { id: 11, parent: 4, text: "test" }, 
    { id: 5, parent: 1, text: "test"}, 
    { id: 6, parent: 1, text: "test"}, 
    { id: 7, parent: 1, text: "test"},  
    { id: 8, parent: 1, text: "test"}, 
    { id: 9, parent: 1, text: "test"} 
] 

这样你就可以轻松地更新您的条目是这样的:

function updateObjectByID(id, text) { 
    for(var i = 0; i < this.Steps.length; i++) { 
     if(this.Steps[i].id === id) { 
      this.Steps[i].text = text; 
      break; 
     } 
    } 
} 

具有额外属性parent你仍然可以很容易地得到所有的孩子这样的元素:

function getChildrenByID(id) { 
    var array = []; 
    for(var i = 0; i < this.Steps.length; i++) { 
     if(this.Steps[i].parent === id) { 
      array.push(this.Steps[i]); 
     } 
    } 
    return array; 
} 
+0

哇,这是一个效率低下的数据结构! – Bergi

+0

@Bergi:是吗? – Amberlamps

+0

是的,不是直接通过属性访问任何东西,你总是必须过滤整个数组。 – Bergi

0

您必须递归下降您的树结构搜索与目标“id”的对象并替换它的文本。例如:

function updateObjectByID(obj, id, text) { 
    if (!obj) return; 
    if (obj.id === id) { 
    obj.text = text; 
    } else if ((typeof(obj)==='object') && (obj.constructor===Array)) { 
    for (var i=0; i<obj.length; i++) { 
     updateObjectByID(obj[i], id, text); 
    } 
    } else if (obj.childSteps) { 
    updateObjectByID(obj.childSteps, id, text); 
    } 
} 

updateObjectByID(this.Steps, 11, 'String to be set'); 

但是,这个解决方案可以通过修剪树来优化。

+0

请注意,'this.Steps'是一个数组,而不是“根步骤”。 – Bergi

0
function updateObjectByID(id, text) { 
    (function setText(steps) { 
     for(var i = 0; i < steps.length; i++){ 
      var step = steps[i]; 
      if(step.id === id){ 
       step.text = text; 
      } 
      if ("childSteps" in step){ 
       setText(step.childSteps); 
      } 
     } 
    })(this.Steps); 
} 

这里是演示。 http://jsfiddle.net/qDWX8/

+0

这个看起来几乎和Bergis一样。除了我没有看到地图对象。而且这个也可以。看到这一点,我不明白为什么我的第一个版本的功能不工作。他们几乎与此相同,但结果是函数作用域中的对象已更新(obj),但未在我的主集合(this.Steps)中更新。 – Tigoes