¿Cuál es la forma más rápida de interpretar una cadena de accesor de atributo de objeto JavaScript anidado?

StackOverflow https://stackoverflow.com/questions/7803246

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?

¿Fue útil?

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 con i < test.length (podría optimizarse de todos modos)
  • Reemplazar la división con substringarena indexOfs
  • 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')
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top