如何从描述地址的字符串访问对象子项

时间:2013-09-24 14:26:52

标签: javascript

如果我有这样的对象......

var rooter = {
    name: 'Billy',
    lastName: 'Moon',
    height: '1.4m'
}

我可以从像这样的变量中访问属性......

var name = "name"
console.log(rooter[name])

var arb = "height"
console.log(rooter[arb])

快乐的日子!

但是,如果我有一个更深层次的嵌套对象,我想得到一个字符串中的地址所描述的叶子......

var rooter = {
    user: {
        firstName: 'Billy',
        lastName: 'Moon',
        arbitrary: {
            namespace: {
                height: '1.4m'
            }
        }
    }
}


var name = "user.lastName"
console.log(rooter[name]) // does not work

var arb = "user.arbitrary.namespace.height"
console.log(rooter[arb]) // does not work

没有骰子:(

如何从描述路径的字符串中访问任意对象叶片?

编辑:找到带下划线的方法......

_.reduce(arb.split('.'), function(m, n){ return m[n] }, rooter)

以及IE 9及以上版本......

arb.split('.').reduce(function(m, n){ return m[n] }, rooter)

4 个答案:

答案 0 :(得分:1)

我环顾四周,发现:  Access object child properties using a dot notation string 这似乎是你问题的答案。

您可以通过几种方式访问​​对象中的不同后代。 例如,您可以按顺序执行rooter [' name'] ['任意'] ['命名空间'] [' height']获得高度的值。但这似乎认为它可能不是你想要的。

在那篇文章中,答案最终是你要编写一个自己的方法来做到这一点,你将在其中接受一个由点分隔并将其拆分的字符串。然后你会找到该元素并返回该对象。

答案 1 :(得分:0)

您可以使用eval(这通常是一个坏主意):

eval('rooter.' + name);

可能更好的方法是:

function namespace(namespaceString) {
    var parts = namespaceString.split('.'),
        parent = window,
        currentPart = '';    

    for(var i = 0, length = parts.length; i < length; i++) {
        currentPart = parts[i];
        parent[currentPart] = parent[currentPart] || {};
        parent = parent[currentPart];
    }

    return parent;
}

console.log(namespace('rooter.user.firstName'));

答案 2 :(得分:0)

查看此代码:

function access(obj, prop, defVal) {
    var objectNames = prop.split(".");

    var curObj = obj;

    for (var i = 0, len = objectNames.length; i < len; i++) {
        curObj = curObj[objectNames[i]];
        if (typeof curObj === 'undefined') {
            return defVal;
        }
    }
    return curObj;
}

jsFiddle

答案 3 :(得分:0)

递归方法(from this question

var rooter = { user: { firstName: 'Billy', lastName: 'Moon', arbitrary: { namespace: { height: '1.4m' } } } };

var arb = "user.arbitrary.namespace.height";

fromPathString = function(pathString, targetObject){
    pathString = pathString.split('.');
    for(var i = 0; i < pathString.length; i++){
        targetObject = (targetObject[pathString[i]])? targetObject[pathString[i]] : targetObject[pathString[i]] = {};
    };
    return targetObject
}

console.log(fromPathString(arb, rooter))

减少方法

arb.split('.').reduce(function(m, n){ return m[n] }, rooter)

因为.reduce与所有浏览器不兼容......

Feature Chrome  Firefox (Gecko) Internet Explorer   Opera   Safari
Basic support   (Yes)   3.0 (1.9)   9   10.5    4.0

为IE 9及以下版本的Shim ...(from MDN

在任何阵列上调用.reduce之前放置......

if ('function' !== typeof Array.prototype.reduce) {
  Array.prototype.reduce = function(callback, opt_initialValue){
    'use strict';
    if (null === this || 'undefined' === typeof this) {
      // At the moment all modern browsers, that support strict mode, have
      // native implementation of Array.prototype.reduce. For instance, IE8
      // does not support strict mode, so this check is actually useless.
      throw new TypeError(
          'Array.prototype.reduce called on null or undefined');
    }
    if ('function' !== typeof callback) {
      throw new TypeError(callback + ' is not a function');
    }
    var index, value,
        length = this.length >>> 0,
        isValueSet = false;
    if (1 < arguments.length) {
      value = opt_initialValue;
      isValueSet = true;
    }
    for (index = 0; length > index; ++index) {
      if (this.hasOwnProperty(index)) {
        if (isValueSet) {
          value = callback(value, this[index], index, this);
        }
        else {
          value = this[index];
          isValueSet = true;
        }
      }
    }
    if (!isValueSet) {
      throw new TypeError('Reduce of empty array with no initial value');
    }
    return value;
  };
}