给定一个JavaScript对象,

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

和字符串

"a.b"

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

var val = obj.a.b

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


当前回答

你可以通过点表示法获得对象成员的值,只需一行代码:

new Function('_', 'return _.' + path)(obj);

对你来说:

var obj = { a: { b: '1', c: '2' } }
var val = new Function('_', 'return _.a.b')(obj);

为了简化,你可以这样写一个函数:

function objGet(obj, path){
    return new Function('_', 'return _.' + path)(obj);
}

解释:

Function构造函数创建一个新的Function对象。在JavaScript中,每个函数实际上都是一个function对象。使用function构造函数显式创建函数的语法如下:

new Function ([arg1[, arg2[, ...argN]],] functionBody)

其中arguments(arg1到argN)必须是一个对应于有效javaScript标识符的字符串,functionBody是一个包含包含函数定义的javaScript语句的字符串。

在我们的例子中,我们利用字符串函数体来检索点表示法的对象成员。

希望能有所帮助。

其他回答

你可以用lodash。get

在安装(npm i lodash.get)后,像这样使用它:

const get = require('lodash.get');

const myObj = { 
    user: { 
        firstName: 'Stacky', 
        lastName: 'Overflowy',
        list: ['zero', 'one', 'two']
    }, 
    id: 123 
};

console.log(get(myObj, 'user.firstName')); // outputs Stacky
console.log(get(myObj, 'id'));             // outputs 123
console.log(get(myObj, 'user.list[1]'));   // outputs one

// You can also update values
get(myObj, 'user').firstName = 'John';

这是我的实现

实现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'

如果您希望以尽可能快的方式做到这一点,同时处理与路径解析或属性解析有关的任何问题,请检查path-value。

const {resolveValue} = require('path-value');

const value = resolveValue(obj, 'a.b.c');

该库是100%的TypeScript,适用于NodeJS +所有web浏览器。它是完全可扩展的,你可以使用较低级别的resolvePath,如果你愿意,你可以用自己的方式处理错误。

const {resolvePath} = require('path-value');

const res = resolvePath(obj, 'a.b.c'); //=> low-level parsing result descriptor
var find = function(root, path) {
  var segments = path.split('.'),
      cursor = root,
      target;

  for (var i = 0; i < segments.length; ++i) {
   target = cursor[segments[i]];
   if (typeof target == "undefined") return void 0;
   cursor = target;
  }

  return cursor;
};

var obj = { a: { b: '1', c: '2' } }
find(obj, "a.b"); // 1

var set = function (root, path, value) {
   var segments = path.split('.'),
       cursor = root,
       target;

   for (var i = 0; i < segments.length - 1; ++i) {
      cursor = cursor[segments[i]] || { };
   }

   cursor[segments[segments.length - 1]] = value;
};

set(obj, "a.k", function () { console.log("hello world"); });

find(obj, "a.k")(); // hello world

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

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