Acceso a una propiedad de objeto con un nombre calculado dinámicamente

6 minutos de lectura

Avatar de usuario de RichW
RicoW

Estoy tratando de acceder a una propiedad de un objeto usando un nombre dinámico. es posible?

const something = { bar: "Foobar!" };
const foo = 'bar';
something.foo; // The idea is to access something.bar, getting "Foobar!"

  • Véase también acceso a la propiedad: ¿notación de puntos frente a corchetes? y ¿Cómo agrego una propiedad a un objeto usando una variable como nombre?

    – Bergi

    18 de noviembre de 2014 a las 6:11

Avatar de usuario de Jan Hančič
Jan Hančič

Existen dos formas de acceder a las propiedades de un objeto:

  • Notación de puntos: something.bar
  • Notación de corchetes: something['bar']

El valor entre paréntesis puede ser cualquier expresión. Por lo tanto, si el nombre de la propiedad se almacena en una variable, debe usar la notación de corchetes:

var something = {
  bar: 'foo'
};
var foo = 'bar';

// both x = something[foo] and something[foo] = x work as expected
console.log(something[foo]);
console.log(something.bar)

  • cuidado con esto: los compiladores de javascript generarán un error aquí ya que no cambian el nombre de las cadenas pero sí cambian el nombre de las propiedades del objeto

    – chacham15

    6 de diciembre de 2011 a las 8:40

  • Más información sobre por qué esto es posible: los objetos JS son matrices asociativas, por eso. Otras lecturas: quirksmode.org/js/associative.html stackoverflow.com/questions/14031368/…

    – Sudhanshu Mishra

    3 de junio de 2014 a las 9:00

  • @dotnetguy No, no lo son. Las matrices son objetos que se heredan del prototipo de objeto JS simple y, por lo tanto, puede agregar propiedades a medida que avanza como cualquier objeto simple. El comportamiento ‘asociativo’ es más parecido a un objeto que a una matriz. No puede iterar la versión ‘asociativa’ mediante un índice simple, por lo que no muestra un comportamiento similar al de una matriz. Puede definir su matriz ‘asociativa’ como {} o [] y trátelo de la misma manera en cualquier caso en lo que respecta al acceso aleatorio a la propiedad.

    – Wombat vencido

    3 de enero de 2017 a las 16:01

  • @VanquishedWombat ¿No está seguro de a qué se refiere su objeción? ¿No dije que los objetos JS son matrices?

    – Sudhanshu Mishra

    6 de enero de 2017 a las 0:30

  • Absténgase de usar foo-bar en el futuro… Esta explicación está muy confusa.

    – Cornelio

    25 de enero a las 3:33

avatar de usuario de abahet
abahet

Esta es mi solución:

function resolve(path, obj) {
    return path.split('.').reduce(function(prev, curr) {
        return prev ? prev[curr] : null
    }, obj || self)
}

Ejemplos de uso:

resolve("document.body.style.width")
// or
resolve("style.width", document.body)
// or even use array indexes
// (someObject has been defined in the question)
resolve("part.0.size", someObject) 
// returns null when intermediate properties are not defined:
resolve('properties.that.do.not.exist', {hello:'world'})

  • Excelente respuesta, consulte también: stackoverflow.com/questions/37510640/…

    – Julián Caballero

    3 de enero de 2019 a las 13:45

  • Me inspiraste para crear una versión mejorada que permite la notación de corchetes y los nombres de propiedades con espacios, así como la validación de las entradas: it.knightnet.org.uk/kb/node-js/get-properties

    – Julián Caballero

    3 de enero de 2019 a las 14:04

  • Me encanta esta solución. Sin embargo, estoy tratando de modificar los valores en el objeto original, parece que su función devuelve una subcopia del objeto. ¿Es posible cambiarlo para que al modificar el objeto devuelto se modifique el original?

    – Águila1

    28 de febrero de 2020 a las 17:39

  • También me gustaría ver la versión de “valor establecido” de esto.

    – GaryO

    21 de agosto de 2020 a las 21:05

  • ¡Gran respuesta! Funciona para propiedades anidadas profundas.

    – NeNaD

    21 de enero a las 14:56

En javascript podemos acceder con:

  • notación de puntos – foo.bar
  • corchetes – foo[someVar] o foo["string"]

Pero solo el segundo caso permite acceder a las propiedades dinámicamente:

var foo = { pName1 : 1, pName2 : [1, {foo : bar }, 3] , ...}

var name = "pName"
var num  = 1;

foo[name + num]; // 1

// -- 

var a = 2;
var b = 1;
var c = "foo";

foo[name + a][b][c]; // bar

  • Estoy mirando 2,000 líneas de declaraciones if porque el desarrollador anterior no usó corchetes y accedió estáticamente a las propiedades del objeto mediante notación de puntos. Es para una aplicación de proceso de aprobación que tiene 7 aprobadores diferentes y los pasos son todos iguales. /rotura

    – Chad

    7 de junio de 2018 a las 14:28


avatar de usuario de zloctb
zloctb

El siguiente es un ejemplo de ES6 de cómo puede acceder a la propiedad de un objeto utilizando un nombre de propiedad que se ha generado dinámicamente mediante la concatenación de dos cadenas.

var suffix = " name";

var person = {
    ["first" + suffix]: "Nicholas",
    ["last" + suffix]: "Zakas"
};

console.log(person["first name"]);      // "Nicholas"
console.log(person["last name"]);       // "Zakas"

Se llama nombres de propiedades calculadas

Avatar de usuario de Gorka Hernandez
Gorka Hernández

Puede lograr esto de varias maneras diferentes.

let foo = {
    bar: 'Hello World'
};

foo.bar;
foo['bar'];

La notación de paréntesis es especialmente poderosa ya que le permite acceder a una propiedad basada en una variable:

let foo = {
    bar: 'Hello World'
};

let prop = 'bar';

foo[prop];

Esto se puede extender para recorrer cada propiedad de un objeto. Esto puede parecer redundante debido a construcciones de JavaScript más nuevas, como for… of…, pero ayuda a ilustrar un caso de uso:

let foo = {
    bar: 'Hello World',
    baz: 'How are you doing?',
    last: 'Quite alright'
};

for (let prop in foo.getOwnPropertyNames()) {
    console.log(foo[prop]);
}

Tanto la notación de puntos como la de corchetes también funcionan como se esperaba para los objetos anidados:

let foo = {
    bar: {
        baz: 'Hello World'
    }
};

foo.bar.baz;
foo['bar']['baz'];
foo.bar['baz'];
foo['bar'].baz;

Desestructuración de objetos

También podríamos considerar la desestructuración de objetos como un medio para acceder a una propiedad en un objeto, pero de la siguiente manera:

let foo = {
    bar: 'Hello World',
    baz: 'How are you doing?',
    last: 'Quite alright'
};

let prop = 'last';
let { bar, baz, [prop]: customName } = foo;

// bar="Hello World"
// baz = 'How are you doing?'
// customName="Quite alright"

Avatar de usuario de JJJ
JJJ

Puedes hacerlo así usando Lodash get

_.get(object, 'a[0].b.c');

ACTUALIZADO

Acceder a las propiedades raíz de un objeto se logra fácilmente con obj[variable], pero anidarse complica las cosas. No escribir código ya escrito, sugiero usar lodash.get.

Ejemplo

// Accessing root property
var rootProp = 'rootPropert';
_.get(object, rootProp, defaultValue);

// Accessing nested property
var listOfNestedProperties = [var1, var2];
_.get(object, listOfNestedProperties);

Lodash get se puede usar de diferentes maneras, la documentación lodash.obtener

  • Lo mejor es evitar el uso eval cuando sea posible. stackoverflow.com/questions/86513/…

    – Lucas

    23 de junio de 2015 a las 18:07

  • Usando eval porque algo tan trivial como acceder a las propiedades es simplemente excesivo y difícilmente aconsejable bajo ninguna circunstancia. ¿Qué es “problemas”? obj['nested']['test'] funciona muy bien y no requiere que incruste código en cadenas.

    – Kyll

    23 de octubre de 2015 a las 10:14

  • eval es tres veces más lento o más, no se lo recomendaría a los novatos porque podría enseñarles malos hábitos. yo suelo obj['nested']['value'] – ¡Recuerden niños, eval es malvado!

    – irregular suave

    26 de noviembre de 2015 a las 1:25


  • @Luke Ahora es el único que quiere traer a Lodash _.get a la mesa. Creo que esta respuesta merece ahora votos a favor en lugar de votos a la baja. Puede ser exagerado, pero es bueno saber que existe.

    –Emile Bergeron

    20 de diciembre de 2016 a las 21:42

  • Gracias por presentar lodash para esto. Vine aquí por google buscando un método para establecer un valor profundo en un objeto, y usé su método _.set (que es idéntico al anterior pero con el argumento adicional para establecer el valor).

    – TPHughes

    3 de julio de 2018 a las 9:03

¿Ha sido útil esta solución?