将点表示法的 JavaScript 字符串转换为对象引用

Posted

技术标签:

【中文标题】将点表示法的 JavaScript 字符串转换为对象引用【英文标题】:Convert a JavaScript string in dot notation into an object reference 【发布时间】:2011-09-17 15:31:57 【问题描述】:

给定一个 javascript 对象,

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

还有一个字符串

"a.b"

如何将字符串转换为点表示法以便我可以去

var val = obj.a.b

如果字符串只是'a',我可以使用obj[a]。但这更复杂。我想有一些直截了当的方法,但目前我没有想到。

【问题讨论】:

@Andrey eval 是邪恶的;不要使用它 仅供参考:以下是我刚刚进行的一些有趣的速度测试:jsperf.com/dereference-object-property-path-from-string 如果 perf 是一个严肃的考虑因素,并且您经常重复使用相同的路径(例如,在数组过滤器函数中),请使用下面我的回答中描述的 Function 构造函数。当同一路径被使用数千次时,Function 方法的速度可以比每次取消引用时评估或拆分和减少路径的速度快 10 倍以上。 另见Accessing nested JavaScript objects with string key 在某些情况下,您必须使用 eval 或 new Function(),尤其是当您想从模板创建函数时,就像将 JSP 页面转换为 JAVA 一样,不是一种更有效的模板制作方法,这个 eval 是邪恶的教条,这只是一个教条,什么是邪恶的是评估你没有自己创建的脚本,当然在这种精确的情况下没有理由使用评估 【参考方案1】:

如果您想以最快的方式执行此操作,同时处理路径解析或属性解析的任何问题,请查看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

【讨论】:

【参考方案2】:

想把这个放在那里:

function propertyByPath(object, path = '') 
    if (/[,()&|;]/.test(path)) 
        throw 'forbidden characters in path';
    
    return Function(
      ...Object.keys(window).filter(k => window[k] instanceof Window || window[k] instanceof Document),
      "obj",
      `return ((o) => o$!path.startsWith('[') ? '.' : ''$path)(...arguments, obj);`)
    .bind(object)(object);

propertyByPath( a:  b: 'hello1'  , "a.b"); // prints 'hello1'
propertyByPath( a:  b: 'hello2'  , "['a']?.b"); // returns 'hello2'
propertyByPath( a:  b: 'hello2'  , "a.b;console.log()"); // throws exception

上面的代码评估路径,同时努力阻止代码执行,同时进行路径评估并屏蔽 Window 和 Document 对象,如果以某种方式阻止执行没有成功。

我并不是说它是 100% 安全的(尽管我希望看到 cmets 建议可能的绕过)也不是有效的,但它可能适用于路径的灵活性(可选链等)以及需要一些缓解措施。

【讨论】:

以上是关于将点表示法的 JavaScript 字符串转换为对象引用的主要内容,如果未能解决你的问题,请参考以下文章

将点表示法与功能组件一起使用

使用点云库将点云转换为世界坐标

如何在JavaScript中将数字的二进制表示从字符串转换为整数?

将强引用转换为对自身的弱引用

将点转换为矢量线的算法。 (光栅到矢量)

将点坐标转换为新的坐标系