我在这里提供更多方法,这些方法在许多方面看起来更快:
选项1:根据 . 或 [ 或 ] 或 ' 或 " 将字符串分割,反转它,跳过空项。
function getValue(path, origin) {
if (origin === void 0 || origin === null) origin = self ? self : this;
if (typeof path !== 'string') path = '' + path;
var parts = path.split(/\[|\]|\.|'|"/g).reverse(), name;
while (parts.length) { name=parts.pop(); if (name) origin=origin[name]; }
return origin;
}
选项2(除了
eval
之外最快的选项):低级字符扫描(无正则表达式/分割等,只是快速字符扫描)。
注意:此选项不支持索引中的引号。
function getValue(path, origin) {
if (origin === void 0 || origin === null) origin = self ? self : this;
if (typeof path !== 'string') path = '' + path;
var c = '', pc, i = 0, n = path.length, name = '';
if (n) while (i<=n) ((c = path[i++]) == '.' || c == '[' || c == ']' || c == void 0) ? (name?(origin = origin[name], name = ''):(pc=='.'||pc=='['||pc==']'&&c==']'?i=n+2:void 0),pc=c) : name += c;
if (i==n+2) throw "Invalid path: "+path;
return origin;
} // (around 1,000,000+/- ops/sec)
选项3:
(新:选项2扩展以支持引号 - 速度略慢,但仍然很快)
function getValue(path, origin) {
if (origin === void 0 || origin === null) origin = self ? self : this;
if (typeof path !== 'string') path = '' + path;
var c, pc, i = 0, n = path.length, name = '', q;
while (i<=n)
((c = path[i++]) == '.' || c == '[' || c == ']' || c == "'" || c == '"' || c == void 0) ? (c==q&&path[i]==']'?q='':q?name+=c:name?(origin?origin=origin[name]:i=n+2,name='') : (pc=='['&&(c=='"'||c=="'")?q=c:pc=='.'||pc=='['||pc==']'&&c==']'||pc=='"'||pc=="'"?i=n+2:void 0), pc=c) : name += c;
if (i==n+2 || name) throw "Invalid path: "+path;
return origin;
}
JSPerf: http://jsperf.com/ways-to-dereference-a-delimited-property-string/3
在性能方面,"eval(...)"仍然是最好的选择。如果您直接控制属性路径,则使用'eval'不会有任何问题(特别是如果需要速度)。如果要通过网络获取属性路径(在线!?哈哈 :P),那么请使用其他安全的方法。只有白痴才会说根本不要使用"eval",因为有时候确实需要使用它。此外,"它被用于Doug Crockford的JSON解析器。" 如果输入是安全的,那么就没有问题了。用正确的工具做正确的事情,就这样。
var part1name = someObject.part1name;
- Rafay