Здесь я предлагаю больше способов, которые во многих отношениях кажутся более быстрыми:
Вариант 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; // (why reverse? because it's usually faster to pop off the end of an array)
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: ( new : опция 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' (особенно, если требуется скорость). Если вы перетаскиваете пути свойств "по проводу" ( наline !? lol: P), тогда да, используйте что-то еще, чтобы быть в безопасности. Только идиот сказал бы, что никогда не используйте "eval" вообще, поскольку есть веские причины , когда использовать этоКроме того, «Он используется в JSON-парсере Дуга Крокфорда ». Если ввод безопасен, то никаких проблем нет. Используйте правильный инструмент для правильной работы, этоэто.