27 avril 2023

Object.keys, values, entries

Éloignons-nous des structures de données individuelles et parlons des itérations les concernant.

Dans le chapitre précédent, nous avons vu les méthodes map.keys(), map.values(), map.entries().

Ces méthodes sont génériques, il existe une convention de les utiliser pour les structures de données. Si nous devions créer notre propre structure de données, nous devrions aussi les implémenter.

Ils sont pris en charge par :

  • Map
  • Set
  • Array

Les objets simples prennent également en charge des méthodes similaires, mais la syntaxe est un peu différente.

Object.keys, values, entries

Pour les objets simples, les méthodes suivantes sont disponibles :

Veuillez noter les différences (par rapport à map par exemple) :

Map Object
Syntaxe d’appel map.keys() Object.keys(obj), mais pas obj.keys()
Retours iterable “vrai” Array

La première différence est que nous devons appeler Object.keys(obj) et non obj.keys().

Pourquoi cela ? La principale raison est la flexibilité. N’oubliez pas que les objets sont une base de toutes les structures complexes en JavaScript. Ainsi, nous pouvons avoir un objet à nous comme data qui implémente sa propre méthode data.values(). Et nous pouvons toujours appeler Object.values(data).

La seconde différence réside dans le fait que les méthodes Object.* retourne de “réels” objets de tableau, et pas seulement des objets itératifs. C’est principalement pour des raisons historiques.

Par exemple :

let user = {
  name: "John",
  age: 30
};
  • Object.keys(user) = [name, age]
  • Object.values(user) = ["John", 30]
  • Object.entries(user) = [ ["name","John"], ["age",30] ]

Voici un exemple d’utilisation d’Object.values pour boucler les valeurs de propriété :

let user = {
  name: "John",
  age: 30
};

// boucle sur les valeurs
for (let value of Object.values(user)) {
  alert(value); // John, ensuite 30
}
Object.keys/values/entries ignorer les propriétés symboliques

Tout comme une boucle for..in, ces méthodes ignorent les propriétés qui utilisent Symbol(...) comme clés.

D’habitude c’est pratique. Mais si nous voulons aussi des clés symboliques, il existe une méthode distincte Object.getOwnPropertySymbols(obj) qui retourne un tableau composé uniquement de clés symboliques. De plus, la méthde Reflect.ownKeys(obj) renvoie toutes les clés.

Transformer des objets

Les objets manquent de nombreuses méthodes existantes pour les tableaux, par exemple map, filter et autres.

Si nous souhaitons leur appliquer ces méthodes, nous pouvons utiliser Object.entries suivis par Object.fromEntries :

  1. Utilisons Object.entries(obj) pour obtenir un tableau de paires clé / valeur de obj.
  2. Utilisons des méthodes de tableau sur ce tableau, par exemple map, pour transformer ces paires clé / valeur.
  3. Utilisons Object.fromEntries(array) sur le tableau résultant pour le reconvertir en objet.

Par exemple, nous avons un objet avec des prix et aimerions les doubler :

let prices = {
  banana: 1,
  orange: 2,
  meat: 4,
};

let doublePrices = Object.fromEntries(
  // convertir les prix en tableau, mapper chaque paire clé / valeur dans une autre paire
  // puis fromEntries restitue l'objet
  Object.entries(prices).map(entry => [entry[0], entry[1] * 2])
);

alert(doublePrices.meat); // 8

Cela peut sembler difficile au premier abord, mais cela devient facile à comprendre après l’avoir utilisé une ou deux fois. Nous pouvons faire de puissantes chaînes de transformations de cette façon.

Exercices

importance: 5

Il existe un objet salaries avec un nombre arbitraire de salaires.

Ecrivez la fonction sumSalaries(salaries) qui retourne la somme des salaires en utilisant Object.values et la boucle for..of.

Si salaries est vide, le résultat doit être 0.

Par exemple:

let salaries = {
  "John": 100,
  "Pete": 300,
  "Mary": 250
};

alert( sumSalaries(salaries) ); // 650

Open a sandbox with tests.

function sumSalaries(salaries) {

  let sum = 0;
  for (let salary of Object.values(salaries)) {
    sum += salary;
  }

  return sum; // 650
}

let salaries = {
  "John": 100,
  "Pete": 300,
  "Mary": 250
};

alert( sumSalaries(salaries) ); // 650

Ou, éventuellement, nous pourrions aussi obtenir la somme en utilisant Object.values et reduce:

// boucles de reduce sur les salaires,
// en les additionnant
// et retourne le résultat
function sumSalaries(salaries) {
  return Object.values(salaries).reduce((a, b) => a + b, 0) // 650
}

Ouvrez la solution avec des tests dans une sandbox.

importance: 5

Ecrivez la fonction count(obj) qui retourne le nombre de propriétés qu’il y a dans l’objet:

let user = {
  name: 'John',
  age: 30
};

alert( count(user) ); // 2

Essayer d’écrire le code le plus petit possible.

P.S: Ignorez les propriétés symboliques, ne comptez que les propriétés “normales”.

Open a sandbox with tests.

function count(obj) {
  return Object.keys(obj).length;
}

Ouvrez la solution avec des tests dans une sandbox.

Carte du tutoriel