给定一个JavaScript对象,

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

和字符串

"a.b"

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

var val = obj.a.b

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


当前回答

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

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

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

其他回答

function at(obj, path, val = undefined) { // If path is an Array, if (Array.isArray(path)) { // it returns the mapped array for each result of the path return path.map((path) => at(obj, path, val)); } // Uniting several RegExps into one const rx = new RegExp( [ /(?:^(?:\.\s*)?([_a-zA-Z][_a-zA-Z0-9]*))/, /(?:^\[\s*(\d+)\s*\])/, /(?:^\[\s*'([^']*(?:\\'[^']*)*)'\s*\])/, /(?:^\[\s*"([^"]*(?:\\"[^"]*)*)"\s*\])/, /(?:^\[\s*`([^`]*(?:\\`[^`]*)*)`\s*\])/, ] .map((r) => r.source) .join("|") ); let rm; while (rm = rx.exec(path.trim())) { // Matched resource let [rf, rp] = rm.filter(Boolean); // If no one matches found, if (!rm[1] && !rm[2]) { // it will replace escape-chars rp = rp.replace(/\\(.)/g, "$1"); } // If the new value is set, if ("undefined" != typeof val && path.length == rf.length) { // assign a value to the object property and return it return (obj[rp] = val); } // Going one step deeper obj = obj[rp]; // Removing a step from the path path = path.substr(rf.length).trim(); } if (path) { throw new SyntaxError(); } return obj; } // Test object schema let o = { a: { b: [ [ { c: { d: { '"e"': { f: { g: "xxx" } } } } } ] ] } }; // Print source object console.log(JSON.stringify(o)); // Set value console.log(at(o, '.a["b"][0][0].c[`d`]["\\"e\\""][\'f\']["g"]', "zzz")); // Get value console.log(at(o, '.a["b"][0][0].c[`d`]["\\"e\\""][\'f\']["g"]')); // Print result object console.log(JSON.stringify(o));

如果您希望将任何包含点符号键的对象转换为这些键的数组版本,可以使用此方法。


这将转换为

{
  name: 'Andy',
  brothers.0: 'Bob'
  brothers.1: 'Steve'
  brothers.2: 'Jack'
  sisters.0: 'Sally'
}

to

{
  name: 'Andy',
  brothers: ['Bob', 'Steve', 'Jack']
  sisters: ['Sally']
}

convertDotNotationToArray(objectWithDotNotation) {

    Object.entries(objectWithDotNotation).forEach(([key, val]) => {

      // Is the key of dot notation 
      if (key.includes('.')) {
        const [name, index] = key.split('.');

        // If you have not created an array version, create one 
        if (!objectWithDotNotation[name]) {
          objectWithDotNotation[name] = new Array();
        }

        // Save the value in the newly created array at the specific index 
        objectWithDotNotation[name][index] = val;
        // Delete the current dot notation key val
        delete objectWithDotNotation[key];
      }
    });

}

从最初的帖子到现在已经很多年了。 现在有一个很棒的库叫做object-path。 https://github.com/mariocasciaro/object-path

可在NPM和BOWER上使用 https://www.npmjs.com/package/object-path

很简单:

objectPath.get(obj, "a.c.1");  //returns "f"
objectPath.set(obj, "a.j.0.f", "m");

并且适用于深度嵌套的属性和数组。

我通过ninjagecko扩展了这个优雅的答案,这样函数就可以处理点和/或数组样式的引用,并且空字符串会导致父对象返回。

给你:

string_to_ref = function (object, reference) {
    function arr_deref(o, ref, i) { return !ref ? o : (o[ref.slice(0, i ? -1 : ref.length)]) }
    function dot_deref(o, ref) { return ref.split('[').reduce(arr_deref, o); }
    return !reference ? object : reference.split('.').reduce(dot_deref, object);
};

查看我的jsFiddle工作示例:http://jsfiddle.net/sc0ttyd/q7zyd/

几年后,我发现它可以处理范围和数组。如[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