【问题标题】:if i already know an object`s structure,how can i eval the right value to the object?(javascript)如果我已经知道对象的结构,我如何评估对象的正确值?(javascript)
【发布时间】:2018-01-23 00:56:45
【问题描述】:

如果我有这样的对象:

let obj = {
  a:{
    b:{
      c:{
        d:{
         e:'nonono'
       }
     }
   }
 }
}

我知道对象的结构是这样的:

现在我想改变对象的最内层,它是“e”属性。 我想为“e”分配另一个值。 我不想像下面这样的方式:

  1. obj.a.b.c.d.e = 'another value';
  2. var str1 = 'a.b.c.d.e'; obj[str1[0]][str[1]][str[2]][str[3]][str[4]];
  3. var str1 = 'obj.a.b.c.d.e'; var str = str1 + "='another value'"; eval(str);

在这些之上,我可以改变对象值的属性'e', 但我认为表达我的意思并不优雅。

如果我有这样的数组: var arr= [a,b,c,d,e],我想递归一个函数找到对象的最内层,但是我尝试,如果我到达对象的最内层,我失去了对象的引用.....所以我不能更改我想要的对象的值。 我想我会运行这些代码,如果你能帮我运行的话。

let obj = {
  a: {
    b: {
      c: {
        d: {
          e: 'nonono'
        }
      }
    }
  }
}
let arr = ['a', 'b', 'c', 'd', 'e'];
let funKeepCite = (obj, index) => {
  if (obj[arr[index]]) {
    funKeepCite(obj[arr[index]], index + 1);
  } else {
    obj = 'test'
  }
}
funKeepCite(obj, 0)
console.log('the result', obj)

我不能改变值,我想我失去了对象的引用,但我的问题的答案是使用for .. in,它可以保留对象的引用,我对这些感到困惑。

【问题讨论】:

  • "失去对象的引用"?
  • 如果您已经知道它的结构,那么obj.a.b.c.d.e = 'another value' 是更改obj.a.b.c.d.e 值的最明显方法-您的其他两种方法只是a)在2 的情况下是错误的。而且荒谬3.的情况下。
  • 请向我们展示您编写递归函数的尝试,否则我们无法帮助您修复它。
  • 如果你想重复这样做,你可以使用参考:let d = obj.a.b.c.d; d.e = 'yes'。但并不是说这不能直接作用于原始类型。

标签: javascript


【解决方案1】:

也许你想要这种

let obj = {
  a:{
    b:{
      c:{
        d:{
         e:'nonono'
       }
     }
   }
 }
}
function recurse(obj, val){
    for(var k in obj){
        if(typeof obj[k] == 'object') recurse(obj[k], val);
        else if(typeof obj[k] == 'string') obj[k] = val;
    }
}
recurse(obj, 'new');
console.log(obj);

【讨论】:

  • 这会将所有值更改为“新”,而不仅仅是指定值。
  • 是的,这只是建议方法。
  • thankx,我运行代码,它可以工作。但我有一个问题,为什么 'obj[k]' 可以保留 'obj' 的引用,所以它可以更改值.... .
  • 将对象作为参数传递给函数意味着传递对象的引用,当我们更新它的引用时,原始对象也会被更新
  • 好的,我知道你的意思,谢谢,你能帮我看看我上面的例子吗……我失去了为什么我失去了对对象的引用
【解决方案2】:

您不能分配给 obj 这只是一个局部变量,您必须分配给一个属性。仅递归到倒数第二个索引,然后使用最后一个进行赋值:

function funKeepCite(obj,index) {
  if (index < arr.length - 1) {
    funKeepCite(obj[arr[index]], index+1);
  } else if (index < arr.length) {
    obj[arr[index]] = 'test';
  } else
    throw new RangeError("there must be at least one property name in the array");
  }
}

或者,使用带有返回值的递归并始终赋值:

function funKeepCite(obj, index) {
  if (index < arr.length) {
    obj[arr[index]] = funKeepCite(obj[arr[index]], index+1);
    return obj;
  } else {
    return 'test';
  }
}

【讨论】:

  • thanx 我知道你的意思,我忘了我必须将值设置为 last_second 属性。像这些我改变了我的 fun.thx 兄弟,你也很好用。let funKeepCite = (obj,index)=&gt;{ if(typeof obj[arr[index]] == 'object'){ funKeepCite(obj[arr[index]],index+1); }else{ obj[arr[index]] = 'test' } }
【解决方案3】:

我知道这不是最好的方法,但就你的情况而言,“你已经知道对象的结构

函数setInnerObjVal将改变obj中所有最内层对象的值。

let obj = {
  a: {
    b: {
      c: {
        d: {
          e: 'nonono'
        }
      }
    }
  }
  //try uncommenting the below codes
  /*,
  x: {
    y: {
      z: {
        val: 'maybe?'
      }
    }
  }*/
};

function setInnerObjVal(obj1, newVal, callback) {
  for (var i in obj1) {
    if (typeof obj1[i] == 'object') {
      setInnerObjVal(obj1[i], newVal, callback);
    } else {
      obj1[i] = newVal;
      if (typeof callback === 'function')
        callback();
      return;
    }
  }
}

//implement a callback to be called when the function is done.
//just in case your object is way way way deeper and you need to wait for the update to finish
var myCallback = function() {
  console.log(obj);
  //or do something else.
}

setInnerObjVal(obj, 'yesyesyes', myCallback);
//console.log(obj); //this will still log the oldvalue 'nonono' in case obj has a very deep object.

注意:

这个函数会改变obj下的ALL个对象。 (尝试取消注释值 x、y、z、val

【讨论】:

  • 好的,你的代码也可以工作,但结果是最后。不保留旧值,最后`console.log(obj)`,这会改变值,它会记录'yesyesyes' ,就是结果~~
  • 正如我所说的,如果您有一个最内层节点非常深的对象,例如 1000 级或其他东西,这将错过时间。所以,最好的方法是有一个回调函数,它会在递归完成后被递归本身调用。在我的例子中,当然它仍然会记录'yesyesyes',因为obj递归在很短的时间内完成。
猜你喜欢
  • 2014-06-10
  • 2012-02-29
  • 2013-05-27
  • 2010-10-15
  • 1970-01-01
  • 1970-01-01
  • 2021-03-17
  • 1970-01-01
  • 2021-05-19
相关资源
最近更新 更多