Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/409.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:按ID设置嵌套对象值_Javascript_Object_Collections_Nested_Set - Fatal编程技术网

JavaScript:按ID设置嵌套对象值

JavaScript:按ID设置嵌套对象值,javascript,object,collections,nested,set,Javascript,Object,Collections,Nested,Set,我想知道用JavaScript更新多级对象集合成员的最佳方法是什么 以下是我收藏的简化版本: this.Steps = [ { id: 1, text: "test", childSteps: [ { id: 2, text: "test"}, { id: 3, text: "test"}, { id: 4, text: "test", childSteps: [ { id: 10, text: "test"},

我想知道用JavaScript更新多级对象集合成员的最佳方法是什么

以下是我收藏的简化版本:

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');
当我们只有一个级别的对象时,这很容易做到。但是当在多级集合上使用递归时,它变得更加困难

我目前正在使用一个函数来解析整个集合并构建字符串,如下所示:

this.Steps[0].childSteps[3].childSteps[1].text == "string to be set"
然后我对该字符串执行
eval()

我相信可能有一个更干净的解决方案

顺便说一句,使用eval使我的类无法压缩

任何帮助都将不胜感激


提前感谢

您可以通过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;
}

由于使用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;
        }
    }
}
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;
}

您必须递归地沿着树结构向下搜索目标为“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');
函数updateObjectByID(对象、id、文本){
如果(!obj)返回;
if(obj.id==id){
obj.text=文本;
}else if((typeof(obj)=='object')&(obj.constructor==数组)){
对于(var i=0;i
函数updateObjectByID(id,文本){
(函数setText(步骤){
对于(var i=0;i

这是演示。

“解析整个集合”…然后在此之后,您仍然必须使用
eval
?不敢相信,请向我们展示该代码。事实上,我正在分析整个集合并生成字符串以更新集合成员。如果我更改对象参数,它将仅在对象的引用上更改,而不会在我的集合上更改,因为在执行递归时将childSteps作为参考发送。我无法将其粘贴为答案,因此我将编辑问题请注意
this.Steps
是一个数组,而不是“根步骤”.Wow,这是一个低效的数据结构!是的,您不必直接通过属性访问任何内容,而必须始终筛选整个阵列。这也是一个有趣的解决方案,但问题是我的集合是从后端发送的,其他所有内容都像现在一样使用它,因此这将是一项艰巨的工作。woow此项工作:)。但我真的不明白怎么做!?!无论如何,非常感谢您的帮助!它们只是对
步骤
数组中完全相同的对象的引用。关于简化版本…该函数正在执行许多其他操作,然后只更新一个对象。它正在管理冲突的步骤(如果选择一个,则取消选择另一个等)有时,在实际找到对象之前需要对命令进行求值。我知道此解决方案非常难看且效率低下,但现在使用上面的解决方案,它将像医院一样干净。我看到MAP对象包含同一级别的所有步骤,但我不明白它是如何更改的。更新MAP[某物]时步骤成员对象值只是指向某些内存的指针。因此,
this.Steps[0].childSteps[1]
map[3]
指向完全相同的对象。如果更改该对象的属性,则无论从哪个引用查看该对象,都可以看到它。此对象与Bergis对象几乎相同。只是我没有看到地图对象。此对象也可以工作。看到这一点,我不明白为什么我的第一个版本的该函数无法工作。它们与此基本相同,但结果是更新了functions范围(obj)中的对象,但没有更新我的主集合(this.Steps)。
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');
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);
}