¿Cuál es la forma más rápida de interpretar una cadena de accesor de atributo de objeto JavaScript anidado?
-
25-10-2019 - |
Pregunta
Digamos que tengo una estructura de objetos anidados como:
var o = { a: { b: { c: 1 } } };
y tengo un accesor String
me gusta "a.b.c"
.
¿Cuál es la función más rápida para devolver el valor anidado especificado (a cualquier profundidad [1..n])?
Es decir, en este caso, getNested(o, 'a.b.c') === 1
y getNested(o, 'a') === {b:{c:1}}
.
¿Cuál es la mejor implementación de getNested
?
Solución
Odio dar una respuesta sin perfilar el código yo mismo, pero dado eso eval
es probablemente lento y forEach
es más lento que simplemente correr a través de un for-bucle, comenzaría con:
// precondtion: path is a nonempty string
function getNested(obj, path) {
var fields = path.split(".");
var result = obj;
for (var i = 0, n = fields.length; i < n; i++) {
result = result[fields[i]];
}
return result;
}
Pero probaría esto con otros enfoques.
No creo que tratar de optimizar la construcción de la matriz de split
valdría la pena, pero esto es solo una cosa para probar si está interesado en la la manera más rápida.
APÉNDICE
Aquí hay una transcripción para que pueda verlo en acción:
$ node
> function getNested(obj, path) {
... var fields = path.split(".");
... var result = obj;
... for (var i = 0, n = fields.length; i < n; i++) {
... result = result[fields[i]];
... }
... return result;
... }
> var o = { a: { b: { c: 1 } } };
> getNested(o, "a")
{ b: { c: 1 } }
> getNested(o, "a.b.c")
1
** Anexo 2 **
Así que avergonzando, olvidé el var
en frente de result
antes de. ¡Eso podría acelerar un poco!
Otras cosas para probar:
- Olvídate de la "optimización" con
n
Y solo haga la prueba de bucle coni < test.length
(podría optimizarse de todos modos) - Reemplazar la división con
substring
arenaindexOf
s - Hacer la división con un regex
/\./
en lugar de una cadena en bruto"."
Otros consejos
Una variante más:
function getNested(obj, path) {
path.replace(/[^\.]+/g, function (p) {
obj = obj[p];
});
return obj;
}
Quizás algo como esto:
function getNested(o, path) {
var parts = path.split('.');
var member = o;
while (member && parts.length) {
member = member[parts.shift()];
}
return member;
}
Probablemente no sea la solución más rápida posible, pero podría ser un punto de partida útil.
try{
var prop=eval(string);
}
catch(er){
prop=undefined;
}
Mi acercamiento
var o = { a: { b: { c: 1 } } };
var getNested = function(p) {
var t;
p.split('.').forEach(function(e) {
t = o[e] || t[e]
});
return t
}
puedes probar:
getNested('a.b.c')