Object.keys, values, entries
En lugar de enfocarnos en estructuras de datos individuales, hablemos sobre cómo iterar sobre ellas.
En el capítulo anterior, discutimos los métodos map.keys()
, map.values()
, y map.entries()
.
Estos métodos son genéricos y hay un consenso general sobre su uso para diversas estructuras de datos. Si alguna vez creamos nuestra propia estructura de datos, también deberíamos implementar estos métodos.
Son compatibles con:
- Map
- Set
- Array
Los objetos simples también tienen métodos similares, aunque la sintaxis es un poco diferente.
Object.keys, values, entries
Para objetos simples, los métodos disponibles son:
Object.keys(obj)
– devuelve un array de claves.Object.values(obj)
– devuelve un array de valores.Object.entries(obj)
– devuelve un array de pares [clave, valor].
Observe las diferencias en comparación con Map
, por ejemplo:
Map | Objeto |
---|---|
Sintaxis de llamada | map.keys() |
Devuelve | iterable |
La primera diferencia es que tenemos que llamar a Object.keys(obj)
en lugar de obj.keys()
.
¿Por qué es esto? La razón principal es la flexibilidad. Recuerde que los objetos son la base de todas las estructuras complejas en JavaScript. Entonces, podemos tener un objeto propio como data
que implemente su propio método data.values()
. Aún así, podemos llamar a Object.values(data)
en él.
La segunda diferencia es que los métodos Object.*
devuelven objetos de array «reales», no solo un iterable. Esto se debe principalmente a razones históricas.
Por ejemplo:
let user = {
name: "John",
age: 30
};
Object.keys(user) // ["name", "age"]
Object.values(user) // ["John", 30]
Object.entries(user) // [["name", "John"], ["age", 30]]
Aquí hay un ejemplo del uso de Object.values
para recorrer los valores de propiedad:
let user = {
name: "John",
age: 30
};
// recorrer los valores
for (let value of Object.values(user)) {
console.log(value); // John, luego 30
}
Object.keys/values/entries ignoran propiedades simbólicas
Al igual que un bucle for..in
, estos métodos ignoran las propiedades que usan Symbol(...)
como nombre de propiedades.
Generalmente, esto es conveniente. Pero si también queremos propiedades simbólicas, entonces hay un método separado Object.getOwnPropertySymbols
que devuelve un array únicamente con propiedades simbólicas. También existe el método Reflect.ownKeys(obj)
que devuelve todas las propiedades.
Transformando objetos
Los objetos no tienen muchos de los métodos que existen para los arrays, como map
, filter
y otros.
Si queremos aplicar estos métodos, podemos usar Object.entries
seguido de Object.fromEntries
:
- Use
Object.entries(obj)
para obtener un array de pares clave/valor deobj
. - Use métodos de array en ese array, como
map
para transformar estos pares clave/valor. - Use
Object.fromEntries(array)
en el array resultante para convertirlo de nuevo en un objeto.
Por ejemplo, supongamos que tenemos un objeto con precios y queremos duplicarlos:
let prices = {
banana: 1,
orange: 2,
meat: 4,
};
let doublePrices = Object.fromEntries(
// convertir precios a array, mapear cada par clave/valor a otro par
// y luego fromEntries nos devuelve el objeto
Object.entries(prices).map(([key, value]) => [key, value * 2])
);
console.log(doublePrices.meat); // 8
Puede parecer complicado al principio, pero se vuelve fácil de entender después de usarlo una o dos veces. Podemos hacer transformaciones poderosas en cadena de esta manera.