将点表示法的 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]
。但这更复杂。我想有一些直截了当的方法,但目前我没有想到。
【问题讨论】:
@Andreyeval
是邪恶的;不要使用它
仅供参考:以下是我刚刚进行的一些有趣的速度测试: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 字符串转换为对象引用的主要内容,如果未能解决你的问题,请参考以下文章