给定一个JavaScript对象,

var obj = { a: { b: '1', c: '2' } }

和字符串

"a.b"

我怎么把字符串转换成点符号呢

var val = obj.a.b

如果字符串只是'a',我可以使用obj[a]。但这个更复杂。我想应该有什么简单的方法,但现在想不起来了。


当前回答

冒着白费口舌的风险…… 我发现这在遍历嵌套对象以引用相对于基对象或具有相同结构的类似对象的位置时非常有用。为此,这对于嵌套的对象遍历函数很有用。注意,我使用了一个数组来保存路径。将其修改为使用字符串路径或数组是很简单的。还要注意,您可以将“undefined”赋值给该值,这与其他一些实现不同。

/* * Traverse each key in a nested object and call fn(curObject, key, value, baseObject, path) * on each. The path is an array of the keys required to get to curObject from * baseObject using objectPath(). If the call to fn() returns falsey, objects below * curObject are not traversed. Should be called as objectTaverse(baseObject, fn). * The third and fourth arguments are only used by recursion. */ function objectTraverse (o, fn, base, path) { path = path || []; base = base || o; Object.keys(o).forEach(function (key) { if (fn(o, key, o[key], base, path) && jQuery.isPlainObject(o[key])) { path.push(key); objectTraverse(o[key], fn, base, path); path.pop(); } }); } /* * Get/set a nested key in an object. Path is an array of the keys to reference each level * of nesting. If value is provided, the nested key is set. * The value of the nested key is returned. */ function objectPath (o, path, value) { var last = path.pop(); while (path.length && o) { o = o[path.shift()]; } if (arguments.length < 3) { return (o? o[last] : o); } return (o[last] = value); }

其他回答

几年后,我发现它可以处理范围和数组。如[b] [c] .d.etc

function getScopedObj(scope, str) {
  let obj=scope, arr;

  try {
    arr = str.split(/[\[\]\.]/) // split by [,],.
      .filter(el => el)             // filter out empty one
      .map(el => el.replace(/^['"]+|['"]+$/g, '')); // remove string quotation
    arr.forEach(el => obj = obj[el])
  } catch(e) {
    obj = undefined;
  }

  return obj;
}

window.a = {b: {c: {d: {etc: 'success'}}}}

getScopedObj(window, `a.b.c.d.etc`)             // success
getScopedObj(window, `a['b']["c"].d.etc`)       // success
getScopedObj(window, `a['INVALID']["c"].d.etc`) // undefined

如果你想把一个字符串点符号转换成一个对象,我已经做了一个方便的小助手,它可以用dotPathToObject(" a.b.c.d ")将一个值为e的字符串转换为a.b.c.d。D ", "value")返回:

  {
    "a": {
      "b": {
        "c": {
          "d": "value"
        }
      }
    }
  }

https://gist.github.com/ahallora/9731d73efb15bd3d3db647efa3389c12

我想把这个说出来:

function propertyByPath(object, path = '') {
    if (/[,(){}&|;]/.test(path)) {
        throw 'forbidden characters in path';
    }
    return Function(
      ...Object.keys(window).filter(k => window[k] instanceof Window || window[k] instanceof Document),
      "obj",
      `return ((o) => o${!path.startsWith('[') ? '.' : ''}${path})(...arguments, obj);`)
    .bind(object)(object);
}
propertyByPath({ a: { b: 'hello1' } }, "a.b"); // prints 'hello1'
propertyByPath({ a: { b: 'hello2' } }, "['a']?.b"); // returns 'hello2'
propertyByPath({ a: { b: 'hello2' } }, "a.b;console.log()"); // throws exception

上面的代码在执行路径计算和屏蔽Window和Document对象(如果执行阻止不成功的话)的同时,努力防止代码执行。

我并不是说它是100%安全的(尽管我希望看到建议可能绕过的评论)也不是有效的,但在需要路径的灵活性(可选链等)以及一些缓解措施的情况下,它可能是合适的。

这是一个递归的例子。

函数重组(obj,字符串){ Var parts = string.split('.'); var newObj = obj[parts[0]]; If (parts[1]) { 部分。拼接(0,1); var newString = parts.join('.'); return recompose(newObj, newString); } 返回newObj; } var obj ={答:{' 1 ',c:‘2’,d:{答:{b:“胡说”}}}}; console.log(重组(obj, ' a.d.a.b '));/ /等等

你可以使用npm中提供的库,它简化了这个过程。https://www.npmjs.com/package/dot-object

 var dot = require('dot-object');

var obj = {
 some: {
   nested: {
     value: 'Hi there!'
   }
 }
};

var val = dot.pick('some.nested.value', obj);
console.log(val);

// Result: Hi there!