给定一个JavaScript对象,

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

和字符串

"a.b"

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

var val = obj.a.b

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


当前回答

这是我的代码没有使用eval。这也很容易理解。

function value(obj, props) {
  if (!props) 
    return obj;
  var propsArr = props.split('.');
  var prop = propsArr.splice(0, 1);
  return value(obj[prop], propsArr.join('.'));
}

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

console.log(value(obj, 'a.d.a.b')); // Returns blah

其他回答

这是我的实现

实现1

Object.prototype.access = function() {
    var ele = this[arguments[0]];
    if(arguments.length === 1) return ele;
    return ele.access.apply(ele, [].slice.call(arguments, 1));
}

实现2(使用数组reduce而不是slice)

Object.prototype.access = function() {
    var self = this;
    return [].reduce.call(arguments,function(prev,cur) {
        return prev[cur];
    }, self);
}

例子:

var myobj = {'a':{'b':{'c':{'d':'abcd','e':[11,22,33]}}}};

myobj.access('a','b','c'); // returns: {'d':'abcd', e:[0,1,2,3]}
myobj.a.b.access('c','d'); // returns: 'abcd'
myobj.access('a','b','c','e',0); // returns: 11

它也可以处理数组中的对象

var myobj2 = {'a': {'b':[{'c':'ab0c'},{'d':'ab1d'}]}}
myobj2.access('a','b','1','d'); // returns: 'ab1d'

注意,如果你已经在使用Lodash,你可以使用属性或获取函数:

var obj = { a: { b: '1', c: '2' } };
_.property('a.b')(obj); // => 1
_.get(obj, 'a.b'); // => 1

js也有一个属性函数,但是不支持点表示法。

其他的建议有点晦涩难懂,所以我想我应该贡献一下:

Object.prop = function(obj, prop, val){
    var props = prop.split('.')
      , final = props.pop(), p 
    while(p = props.shift()){
        if (typeof obj[p] === 'undefined')
            return undefined;
        obj = obj[p]
    }
    return val ? (obj[final] = val) : obj[final]
}

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

// get
console.log(Object.prop(obj, 'a.c')) // -> 2
// set
Object.prop(obj, 'a.c', function(){})
console.log(obj) // -> { a: { b: '1', c: [Function] } }

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

我用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.首页示例。欢迎通过改变你的函数返回对象,你得到类型安全,自动完成,不容易出现错别字。

我从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]
 }