给定一个JavaScript对象,

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

和字符串

"a.b"

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

var val = obj.a.b

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


当前回答

我通过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/

其他回答

我从Ricardo Tomasi的回答中复制了以下内容,并进行了修改,以创建还不存在的子对象。它的效率有点低(更多的if和创建空对象),但应该很好。

它还允许我们做Object。Prop (obj, 'a.b', false)我们之前做不到。不幸的是,它仍然不允许我们赋值为undefined…我还不知道该怎么做。

/**
 * Object.prop()
 *
 * Allows dot-notation access to object properties for both getting and setting.
 *
 * @param {Object} obj    The object we're getting from or setting
 * @param {string} prop   The dot-notated string defining the property location
 * @param {mixed}  val    For setting only; the value to set
 */
 Object.prop = function(obj, prop, val){
   var props = prop.split('.'),
       final = props.pop(),
       p;

   for (var i = 0; i < props.length; i++) {
     p = props[i];
     if (typeof obj[p] === 'undefined') {
       // If we're setting
       if (typeof val !== 'undefined') {
         // If we're not at the end of the props, keep adding new empty objects
         if (i != props.length)
           obj[p] = {};
       }
       else
         return undefined;
     }
     obj = obj[p]
   }
   return typeof val !== "undefined" ? (obj[final] = val) : obj[final]
 }

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

这是一个递归的例子。

函数重组(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 '));/ /等等

使用数组缩减函数将获得/设置基于提供的路径。

我用a.b.c和a.b.2.c {a:{b:[0,1,{c:7}]}}测试了它,它既可以获取键,也可以将对象更改为设置值

function setOrGet(obj, path=[], newValue){ const l = typeof path === 'string' ? path.split('.') : path; return l.reduce((carry,item, idx)=>{ const leaf = carry[item]; // is this last item in path ? cool lets set/get value if( l.length-idx===1) { // mutate object if newValue is set; carry[item] = newValue===undefined ? leaf : newValue; // return value if its a get/object if it was a set return newValue===undefined ? leaf : obj ; } carry[item] = leaf || {}; // mutate if key not an object; return carry[item]; // return object ref: to continue reduction; }, obj) } console.log( setOrGet({a: {b:1}},'a.b') === 1 || 'Test Case: Direct read failed' ) console.log( setOrGet({a: {b:1}},'a.c',22).a.c===22 || 'Test Case: Direct set failed' ) console.log( setOrGet({a: {b:[1,2]}},'a.b.1',22).a.b[1]===22 || 'Test Case: Direct set on array failed' ) console.log( setOrGet({a: {b:{c: {e:1} }}},'a.b.c.e',22).a.b.c. e===22 || 'Test Case: deep get failed' ) // failed !. Thats your homework :) console.log( setOrGet({a: {b:{c: {e:[1,2,3,4,5]} }}},'a.b.c.e.3 ',22) )

我个人的建议。

除非没有别的办法,否则不要用这种东西!

我看到很多例子,人们用它来翻译json;你会看到locale('app。主页。欢迎')这样的函数。这太糟糕了。如果你已经在object/json中有数据;你知道路径。然后直接使用locale().app.首页示例。欢迎通过改变你的函数返回对象,你得到类型安全,自动完成,不容易出现错别字。

是的,扩展基本原型通常不是一个好主意,但是,如果你把所有扩展放在一个地方,它们可能是有用的。 这是我的方法。

   Object.defineProperty(Object.prototype, "getNestedProperty", {
    value     : function (propertyName) {
        var result = this;
        var arr = propertyName.split(".");

        while (arr.length && result) {
            result = result[arr.shift()];
        }

        return result;
    },
    enumerable: false
});

现在,您将能够获得嵌套的属性,而无需导入模块与函数或复制/粘贴函数。

例子:

{a:{b:11}}.getNestedProperty('a.b'); // Returns 11

js扩展打破猫鼬在我的项目。此外,我还读到它可能会破坏jQuery。所以,永远不要用Next.js的方式:

 Object.prototype.getNestedProperty = function (propertyName) {
    var result = this;
    var arr = propertyName.split(".");

    while (arr.length && result) {
        result = result[arr.shift()];
    }

    return result;
};