Comment avoir une idée de la référence par rapport à la valeur en JavaScript

Cet article explique comment les différents types de données JavaScript se comportent lorsqu'ils sont affectés à une variable. Selon le type de données, la mémoire est allouée différemment pour la stocker. Il peut réserver un nouvel espace pour stocker une copie de la valeur, ou il peut ne pas créer de copie du tout et pointer simplement vers la valeur existante (référence).

Voici mes notes prises en suivant le cours Javascript30 par Wes Bos.

Nombres, chaînes et booléens

En JavaScript, les types primitifs tels que undefined, null, string, number, booleanet symbolsont passés par valeur.

let name = ‘Marina’;let name2 = name;
console.log({name, name2}); >> { name: ‘Marina’, name2: ‘Marina’ }
name = ‘Vinicius’;
console.log({name, name2});>> { name: ‘Vinicius’, name2: ‘Marina’ }

Lorsque la variable nameest affectée, un espace dans la mémoire avec une adresse de 0x001est réservé pour stocker cette valeur. La variable namepointe alors vers cette adresse. La variable name2est alors mise à égalité name. Un nouvel espace dans la mémoire, avec une nouvelle adresse 0x002est alloué et stocke une copie de la valeur stockée dans l'adresse namevers laquelle pointe.

Ainsi, chaque fois que nous voulons modifier la valeur de name, la valeur stockée par name2ne sera pas modifiée, car il s'agit d'une copie, stockée dans un emplacement différent.

Objets et tableaux

Les objets en JavaScript sont passés par référence. Lorsque plusieurs variables sont définies pour stocker un object, arrayou function, ces variables pointeront vers le même espace alloué dans la mémoire.

const animals = ['Cat', 'Dog', 'Horse', 'Snake'];
let animals2 = animals;console.log({animals, animals2});>>{ animals: ['Cat', 'Dog', 'Horse', 'Snake'], animals2: ['Cat', 'Dog', 'Horse', 'Snake']}
animals2[3] = 'Wale';console.log(animals, animals2);>>{ animals: ['Cat', 'Dog', 'Horse', 'Wale'], animals2: ['Cat', 'Dog', 'Horse', 'Wale']}

Lorsque animalsest défini pour stocker un tableau, la mémoire est allouée et une adresse est associée à cette variable. Puis animals2est mis à égal animals. Puisque animalsstocke un tableau, au lieu de créer une copie de ce tableau et une nouvelle adresse dans la mémoire, il animals2est simplement pointé vers le même objet dans l'adresse existante. De cette façon, toutes les modifications apportées à animals2seront prises en compte animals, car elles pointent vers le même emplacement.

Vous verrez le même comportement pour les objets:

const person = { name: 'Marina', age: 29};
let femme = person;femme.age = 18;
console.log({person, femme});>>{ person: { name: 'Marina', age: 18 }, femme: { name: 'Marina', age: 18 }}

Copie d'objets et de tableaux

Puisqu'une simple affectation ne suffit pas pour produire une copie d'un objet, cela peut être réalisé par d'autres approches:

Tableaux

tranche()

let animals2 = animals.slice();animals2[3] = 'Shark';

concat ()

let animals3 = [].concat(animals);animals3[3] = 'Tiger';

propagation (ES6)

let animals4 = [...animals];animals4[3] = 'Lion';

Les modifications n'affecteront que l'objet modifié:

console.log({animals, animals2, animals3, animals4});>>{ animals: ['Cat', 'Dog', 'Horse', 'Snake'], animals2: ['Cat', 'Dog', 'Horse', 'Shark'], animals3: ['Cat', 'Dog', 'Horse', 'Tiger'], animals4: ['Cat', 'Dog', 'Horse', 'Lion']}

Objets

attribuer()

let human = Object.assign({}, person, { age: 20 });
console.log(person, human);>>{ person: { name: 'Marina', age: 29 }, human: { name: 'Marina', age: 20 }}

Clone profond

Il est important de noter que ces méthodes ne sont qu'un niveau. Pour les clones profonds, il existe une méthode mal vue. Utilisez avec précaution.

let femme3 = JSON.parse(JSON.stringify(person));femme3.name = 'Leslie';
console.log(person, femme3);>>{ person: { name: 'Marina', age: 29 }, femme3: { name: 'Leslie', age: 29 }}

Références

  • WesBos - Javascript 30
  • Vous ne connaissez pas JS: portée et fermetures par Kyle Simpson

Publié à l'origine sur marina-ferreira.github.io.