javascript: acceder a una propiedad de objeto con un nombre calculado dinámicamente

CorePress2024-01-24  12

Estoy intentando acceder a una propiedad de un objeto usando un nombre dinámico. ¿Es esto posible?

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

5

Consulte también acceso a la propiedad: ¿notación de puntos versus 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



------------------------------------

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

punto notación: algo.bar Notación entre corchetes: algo['barra']

El valor entre corchetes puede ser cualquier expresión. Por lo tanto, si el nombre de la propiedad se almacena en una variable, debe utilizar la notación entre 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)

Respondido

22 de noviembre de 2010 a las 11:25

Jan Hančič

Jan Hančič

53,5k

17

17 insignias de oro

96

96 insignias de plata

100

100 de bronce insignias

12

47

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 de los objetos

-chacham15

6 de diciembre de 2011 a las 8:40

9

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

- Sudhanshu Mishra

3 junio 2014 a las 9:00

2

@dotnetguy No, no lo son. Las matrices son objetos que heredan del prototipo de objeto JS simple y, por lo tanto, puede agregar propiedades de forma progresiva como cualquier objeto simple. El grupo 'asociativo' El comportamiento es más parecido a un objeto que a una matriz. No se puede iterar el proceso 'asociativo' versión por índice simple, por lo que no muestra un comportamiento similar a una matriz. Puedes definir tu perfil 'asociativo' array como {} o [] y trátelo igual en cualquier caso en lo que respecta al acceso aleatorio a la propiedad.

- Wombat vencido

3 enero 2017 a las 16:01

3

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

- Sudhanshu Mishra

6 enero 2017 a las 0:30

2

Por favor, absténgase de utilizar foo-bar en el futuro... Esta explicación es muy confusa.

- Cornelio

25 de enero de 2022 a las 15:33



------------------------------------

-------------- ------------------

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'})
Respondido al

26 de julio de 2017 a las 8:57

muchos

muchos

10.4k

4

4 insignias de oro

23

23 insignias de bronce

6

4

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

- Julián Caballero

3 enero 2019 a las 13:45

7

Me inspiraste a crear una versión mejorada que permite la notación entre corchetes y el formato. nombres de propiedades con espacios y validar las entradas: it.knightnet.org.uk/kb/node-js/get-properties

- Julián Caballero

3 enero 2019 a las 14:04

3

Me encanta esta solución. Sin embargo, estoy intentando 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/02/2020 a las 17:39

3

También me gustaría ver el "valor establecido" versión de esto.

- GaryO

21/08/2020 a las 21:05

Tenga en cuenta que los motores JS modernos ahora admiten ?., lo que le permite lograr el mismo efecto como este: documento.cuerpo?.estilo?.ancho. No se necesita ninguna función auxiliar. Más información

- Scotty Jamison

2 de diciembre de 2022 a las 21:24



------------------------------------

En javascript podemos acceder con:

notación de puntos - foo.bar corchetes - foo[someVar] o foo["cadena"]

Pero sólo 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

1

13

Estoy mirando 2000 líneas de declaraciones if porque el desarrollador anterior no usaba corchetes y accedía estáticamente a las propiedades de los objetos 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. / rasgar

-Chad

7 junio 2018 a las 14:28



------------------------------------

A continuación se muestra un ejemplo de ES6 de cómo se 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"

Esto se llama nombres de propiedad calculados

Respondido al

2 de agosto de 2016 a las 19:46

zloctb

zloctb

10,8k

9

9 insignias de oro

73

73 insignias de plata

89

89 bronce insignias

0



------------------------------------

Puedes lograr esto de varias maneras diferentes.

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

foo.bar;
foo['bar'];

La notación entre corchetes 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 las nuevas construcciones de JavaScript, 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 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'



------------------------------------

Puedes hacerlo así usando Lodash get

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

6 de septiembre de 2018 a las 6:36

shalonteoh

shalonteoh

2.024

3

3 insignias de oro

16

16 insignias de plata

18

18 insignias de bronce

2

Hay muchas situaciones, como búsquedas profundas de objetos anidados, en las que esta es la única opción.

- Jonathan Kempf

27/06/2019 a las 19:51

No hay suficiente jQuery.

- usuario3840170

7 de abril de 2021 a las 7:18



------------------------------------

ACTUALIZADO

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

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 utilizar de diferentes maneras, la documentación lodash.get

9

5

Es mejor evitar el uso de eval siempre que sea posible. stackoverflow.com/questions/86513/…

- Lucas

23/06/2015 a las 18:07

9

Usar eval para algo tan trivial como acceder a propiedades es simplemente excesivo y poco aconsejable bajo ninguna circunstancia. ¿Qué es el "problema"? obj['nested']['test'] funciona muy bien y no requiere que incrustes código en cadenas.

- Kyll

23/10/2015 a las 10:14

4

La evaluación es tres veces más lenta o más. No recomendaría esto a los novatos porque podría enseñarles malos hábitos. Yo uso obj['nested']['value'] - recuerden niños, ¡eval es malo!

- jaggedsoft

26 de noviembre de 2015 a las 1:25

2

@Luke Ahora es el único que quiere traer a Lodash _.llegar a la mesa. Creo que esta respuesta merece ahora votos a favor en lugar de votos negativos. Puede que sea excesivo, pero es bueno saber que existe.

- Émile Bergeron

20 dic 2016 a las 21:42

2

Gracias por presentar a lodash para esto. Llegué aquí a través de Google buscando un método para establecer un valor en lo profundo de un objeto y utilicé su método _.set (que es idéntico al anterior pero con el argumento adicional del valor a establecer).

-TPHughes

3 de julio de 2018 a las 9:03



------------------------------------

Para acceder a una propiedad dinámicamente, simplemente use corchetes [] de la siguiente manera:

const something = { bar: "Foobar!" };
const userInput = 'bar';
console.log(something[userInput])

El problema

¡Hay un problema importante en esa solución! (Me sorprende que otras respuestas no hayan mencionado esto todavía). A menudo, solo desea acceder a las propiedades que usted mismo ha puesto en ese objeto, no desea heredarlas.d propiedades.

A continuación se muestra una ilustración de este problema. Aquí tenemos un programa que parece inocente, pero tiene un error sutil. ¿Puedes detectarlo?

const agesOfUsers = { sam: 16, sally: 22 }
const username = prompt('Enter a username:')
if (agesOfUsers[username] !== undefined) {
  console.log(`${username} is ${agesOfUsers[username]} years old`)
} else {
  console.log(`${username} is not found`)
}

Cuando se le solicite un nombre de usuario, si proporciona "toString" como nombre de usuario, le dará el siguiente mensaje: "toString tiene la función toString() { [código nativo] } años". El problema es que ageOfUsers es un objeto y, como tal, hereda automáticamente ciertas propiedades como .toString() de la clase Object base. Puede buscar aquí para obtener una lista completa de las propiedades que heredan todos los objetos.

Soluciones Utilice una estructura de datos de mapa en su lugar. El contenido almacenado de un mapa no sufre problemas de prototipo, por lo que proporciona una solución limpia a este problema.

const agesOfUsers = new Map()
agesOfUsers.set('sam', 16)
agesOfUsers.set('sally', 2)
console.log(agesOfUsers.get('sam')) // 16

  

Utilice un objeto con un nulol prototipo, en lugar del prototipo predeterminado. Puede utilizar Object.create(null) para crear dicho objeto. Este tipo de objeto no sufre estos problemas de prototipo, porque lo ha creado explícitamente de manera que no hereda nada.

const agesOfUsers = Object.create(null)
agesOfUsers.sam = 16
agesOfUsers.sally = 22;
console.log(agesOfUsers['sam']) // 16
console.log(agesOfUsers['toString']) // undefined - toString was not inherited

  

Puede usar Object.hasOwn(yourObj, attrName) para verificar primero si la clave dinámica a la que desea acceder está directamente en el objeto y no se hereda (obtenga más información aquí). Esta es una característica relativamente nueva, así que verifique las tablas de compatibilidad antes de incluirla en su código. Antes de que apareciera Object.hasOwn(yourObj, attrName), se lograba el mismo efecto a través de Object.prototype.hasOwnProperty.call(yourObj, attrName). A veces, es posible que también veas código usando yourObj.hasOwnProperty(attrName), que a veces funciona pero tienealgunos errores sobre los que puedes leer aquí.

// Try entering the property name "toString",
// you'll see it gets handled correctly.
const user = { name: 'sam', age: 16 }
const propName = prompt('Enter a property name:')
if (Object.hasOwn(user, propName)) {
  console.log(`${propName} = ${user[propName]}`)
} else {
  console.log(`${propName} is not found`)
}

Si sabe que la clave que está intentando usar nunca será el nombre de una propiedad heredada (por ejemplo, tal vez sean números o todos tengan el mismo prefijo, etc.), puede optar por usar la solución original.



------------------------------------

Me encontré con un caso en el que pensé que quería pasar la "dirección" de una propiedad de objeto como datos a otra función y completar el objeto (con AJAX), buscar desde la matriz de direcciones y mostrarlo en esa otra función. No podía usar la notación de puntos sin hacer acrobacias con cuerdas, así que pensé que una matriz podríasería bueno pasar en su lugar. Terminé haciendo algo diferente de todos modos, pero parecía relacionado con esta publicación.

Aquí hay un ejemplo de un objeto de archivo de idioma como aquel del que quería datos:

const locs = {
  "audioPlayer": {
    "controls": {
      "start": "start",
      "stop": "stop"
    },
    "heading": "Use controls to start and stop audio."
  }
}

Quería poder pasar una matriz como: ["audioPlayer", "controls", "stop"] para acceder al texto del idioma, "stop" en este caso.

Creé esta pequeña función que busca el (primer) parámetro de dirección "menos específico" y reasigna el objeto devuelto a sí mismo. Luego estará listo para buscar el siguiente parámetro de dirección más específico, si existe.

function getText(selectionArray, obj) {
  selectionArray.forEach(key => {
    obj = obj[key];
  });
  return obj;
}

uso:

/* returns 'stop' */
console.log(getText(["audioPlayer", "controls", "stop"], locs)); 

/* returns 'use controls to start and stop audio.' */
console.log(getText(["audioPlayer", "heading"], locs)); 



------------------------------------

ES5 // Verificar variables profundamente anidadas

Este simple fragmento de código puede verificar la existencia de variables/valores profundamente anidados sin tener que verificar cada variable en el camino...

var getValue = function( s, context ){
    return Function.call( context || null, 'return ' + s )();
}

Ej. - una serie de objetos profundamente anidados:

a = [ 
    {
      b : [
          {
             a : 1,
             b : [
                 {
                    c : 1,
                    d : 2   // we want to check for this
                 }
             ]
           }
      ]
    } 
]

En lugar de:

if(a && a[0] && a[0].b && a[0].b[0] && a[0].b[0].b && a[0].b[0].b[0] && a[0].b[0].b[0].d && a[0].b[0].b[0].d == 2 )  // true

Ahora podemos:

if( getValue('a[0].b[0].b[0].d') == 2 ) // true

¡Salud!



------------------------------------

ejemplo de objeto de demostración

let obj = {
    name: {
        first_name: "Bugs",
        last_name: "Founder",
        role: "Programmer"
    }
}

clave de cadena de puntos para obtener el valor de

let key = "name.first_name"

Función

const getValueByDottedKeys = (obj, strKey)=>{
    let keys = strKey.split(".")
    let value = obj[keys[0]];   
    for(let i=1;i<keys.length;i++){
        value = value[keys[i]]
    }
    return value
}

Llamar a la función getValueByDottedKeys

value = getValueByDottedKeys(obj, key)
console.log(value)

salida

Bugs

const getValueByDottedKeys = (obj, strKey)=>{
    let keys = strKey.split(".")
    let value = obj[keys[0]];   
    for(let i=1;i<keys.length;i++){
        value = value[keys[i]]
    }
    return value
}

let obj = {
    name: {
        first_name: "Bugs",
        last_name: "Founder",
        role: "Programmer"
    }
}

let key = "name.first_name"

value = getValueByDottedKeys(obj, key)
console.log(value)



------------------------------------

Hace un tiempo hice una pregunta que se duplicó un poco sobre este tema y, después de una investigación excesiva y de ver que faltaba mucha información que debería estar aquí, siento que tengo algo valioso que agregar a esta publicación anterior.

En primer lugar quiero abordar que existen varias formas de obtener el valor de una propiedad y almacenarlo en una Variable dinámica. En mi humilde opinión, la primera forma más popular y sencilla sería:
let properyValue = element.style['enter-a-property'];

Sin embargo, rara vez sigo esta ruta porque no funciona con valores de propiedad asignados mediante hojas de estilo. Para darte un ejemplo, lo demostraré con un poco de pseudocódigo.

 let elem = document.getElementById('someDiv');
 let cssProp = elem.style['width'];

Usandoel ejemplo de código anterior; Si la propiedad de ancho del elemento div que se almacenó en la variable 'elem' se diseñó en una hoja de estilo CSS y no se diseñó dentro de su etiqueta HTML, sin duda obtendrá un valor de retorno indefinido almacenado dentro. de la variable cssProp. El valor indefinido ocurre porque para obtener el valor correcto, el código escrito dentro de una hoja de estilo CSS debe calcularse para obtener el valor, por lo tanto; debe utilizar un método que calcule el valor de la propiedad cuyo valor se encuentra dentro de la hoja de estilo.

¡De ahora en adelante el método getComputedStyle()!
function getCssProp(){
  let ele = document.getElementById("test");
  let cssProp = window.getComputedStyle(ele,null).getPropertyValue("width");
}

W3Schools getComputedValue Doc. Esto proporciona un buen ejemplo y te permite jugar con él; sin embargo, este enlace Mozilla CSS getComputedValue doc habla sobre la función getComputedValue.n en detalle y debe ser leído por cualquier aspirante a desarrollador que no tenga del todo claro este tema.

Como nota al margen, el método getComputedValue solo obtiene, no establece. Esto, obviamente, es una desventaja importante, sin embargo, existe un método que obtiene hojas de estilo CSS y establece valores, aunque no es Javascript estándar. El método JQuery...
$(selector).css(property,value)

...obtiene y establece. Es lo que uso, el único inconveniente es que debes conocer JQuery, pero honestamente esta es una de las muchas buenas razones por las que todo desarrollador de Javascript debería aprender JQuery, simplemente hace la vida más fácil y ofrece métodos, como este, que no está disponible con Javascript estándar. ¡¡¡Espero que esto ayude a alguien!!!

1

El contenido aquí es un duplicado de muchas otras preguntas y sus respuestas (por ejemplo, JavaScript obtiene estilos, myDiv.style.display devuelve un espacio en blanco cuando se establece en la hoja de estilo maestra). Se debe hacer referencia a esas preguntas y respuestas en lugar de a otra respuesta que diga se está creando lo mismo.

- Mono hereje

25/10/2022 a las 16:01



------------------------------------

Para cualquiera que quiera establecer el valor de una variable anidada, aquí se explica cómo hacerlo:

const _ = require('lodash'); //import lodash module

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.set(object, 'a[0].b.c', 4);
console.log(object.a[0].b.c);
// => 4

Hacerdocumentación: https://lodash.com/docs/4.17.15#set

Además, documentación si desea obtener un valor: https://lodash.com/docs/4.17.15#get

0



------------------------------------

Puedes acceder dinámicamente a la propiedad de un objeto usando la notación entre corchetes. Esto se vería así obj[yourKey] sin embargo, los objetos JavaScript en realidad no están diseñados para actualizarse o leerse dinámicamente. Están pensados ​​para definirse durante la inicialización.

En caso de que desee asignar y acceder dinámicamente a pares clave-valor, debe utilizar un mapa.

const yourKey = 'yourKey';

// initialise it with the value
const map1 = new Map([
  ['yourKey', 'yourValue']
]);

// initialise empty then dynamically assign
const map2 = new Map();
map2.set(yourKey, 'yourValue');

console.log(map1.get(yourKey));
console.log(map2.get(yourKey));

Respondido al

30 de agosto de 2022 a las 8:56

Vicente Menzel

Vincent Menzel

1.040

1

1 insignia de oro

6

6 insignias de plata

17

17 insignias de bronce



------------------------------------

Me encontré con el mismo problema, pero el módulo lodash está limitado al manejar propiedades anidadas. Escribí una solución más general siguiendo la idea de un analizador descendiente recursivo. Esta solución está disponible en el siguiente Gist:

De recursivodesreferenciación de objetos olfativos



------------------------------------

Aquí hay una forma de acceder a la propiedad del objeto dinámicamente. El caso es acceder al objeto JSON en función de los datos de almacenamiento local {preferredIndustry= foodItemsFeatured}

data.foodItemsFeatured para acceder

let storageData = this.data; // JSON Response
let preferredData = localStorage.getItem('preferredIndustry'); //foodItemsFeatured

/* Dynamically access Object's property */
this.preferredFeaturedItems = this.data[preferredData as keyof typeof storageData];



------------------------------------

Encontrar objetos por referencia sin cadenas Tenga en cuenta que asegúrese de que el objeto que pasa esté clonado, yo uso cloneDeep de locorre por eso

si el objeto se parece

const obj = {data: ['an Object',{person: {name: {first:'nick', last:'gray'} }]

la ruta parece

const objectPath = ['data',1,'person',name','last']

luego llame al siguiente método y devolverá el subobjeto por la ruta proporcionada

const child = findObjectByPath(obj, objectPath)
alert( child) // alerts "last"


const findObjectByPath = (objectIn: any, path: any[]) => {
    let obj = objectIn
    for (let i = 0; i <= path.length - 1; i++) {
        const item = path[i]
        // keep going up to the next parent
        obj = obj[item] // this is by reference
    }
    return obj
}



------------------------------------

Puedes usar getter en Javascript

obtener documentos

Compruebe dentro del Objeto si la propiedad en cuestión existe, Si no existe, tómalo de la ventana

const something = {
    get: (n) => this.n || something.n || window[n]
};



------------------------------------

Deberíasy JSON.parse, eche un vistazo a https://www.w3schools.com/js/js_json_parse.asp

const obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}')
console.log(obj.name)
console.log(obj.age)

Su guía para un futuro mejor - libreflare
Su guía para un futuro mejor - libreflare