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

How to access object children from string describing address

本文关键字:访问 对象 字符串 描述 地址      更新时间:2023-09-26

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

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)

我环顾四周,发现: 使用点表示法字符串访问对象子属性这似乎是您问题的答案。

有几种方法可以访问对象中的不同后代。例如,你可以执行rooter['name']['arbitrary']['namespace']['height'],以获得高度的值。但这似乎被认为可能不是您想要的。

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

您可以使用

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'));

查看此代码:

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;
}

js小提琴

归方法(来自这个问题)

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 及更低版本的垫片...(来自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;
  };
}