Donc, je comprends que les tableaux en JavaScript sont mutables.
Cela signifie que si je crée un tableau a
et un tableau b = a
, alors si je modifie un tableau a
, la modification est également visible dans le tableau b
.
Cependant, dans le scénario suivant, je ne comprends pas pourquoi b code> perd la "référence" au tableau
a
.
var a = [1,2,3]; var b = a; console.log('a =', a); console.log('b =', b); a[0] = 4; console.log('a =', a); console.log('b =', b); a = [5,5]; console.log('a =', a); console.log('b =', b);
3 Réponses :
a
et b
ne sont pas des références l'un à l'autre - ce sont des références au même tableau .
Lorsque vous faites a = [5,5]
, vous définissez a
sur un tout nouveau tableau, tandis que b < / code> fait toujours référence à l'ancien.
Et comment pourrais-je dire à b
de garder une référence à tout ce que contient a
?
@DonJoe Soyez plus précis alors, sur la façon dont vous voulez que [5, 5]
affecte les résultats dans a
et b
@DoJoe JavaScript n'a pas la capacité pour les variables de contenir des pointeurs, vous ne pouvez donc pas essayer de définir a à b et que b soit {value: [1,2,3]}
alors vous pouvez définir b.value sur n'importe quoi et a.value changera.
@DonJoe Comme le souligne Taplar, vous devrez élaborer un peu. Il n'y a pas vraiment de moyen inhérent de faire en sorte qu'une variable conserve la valeur d'une autre, bien qu'il existe des solutions de contournement telles que les mentions HMR.
medium.com/@naveenkarippai/... est un assez bon aperçu du fonctionnement des références dans JS
@DonJoe JavaScript n'a pas de pointeurs. Plus d'informations . Techniquement, vous pouvez faire quelque chose comme Object.defineProperty ('window', 'b', get () => this .a);
, mais c'est moche car cela nécessite des globaux et autres.
@tylerRoper ou avec ({a, get b () {return this.a;}}) {...}
;)
@donJoe vous ne pouvez pas avoir de références à des références dans JS (en C, vous pouvez pointer vers un pointeur). Les variables ne peuvent référencer que des valeurs, il n'y a aucun moyen pour une variable de référencer une variable.
@DonJoe au lieu d'un "pointeur" utilise une fonction dans JS. var b = () => a;
var b contient maintenant une fonction qui retournera toujours la valeur courante stockée dans la variable a
. Et dans JS, vous pouvez transmettre cette fonction comme toute autre valeur. C'est la voie à suivre pour JS. Vous souhaitez peut-être en savoir plus sur les fermetures , les rappels et les fonctions en tant que citoyens de première classe .
Regardons la mémoire des ordinateurs¹. Tout d'abord, deux variables sont créées, a
et b
. Ce sont essentiellement des emplacements de mémoire, qui sont remplis avec une valeur:
location | name² | value ------------------------------------- 1 | a | â¡ï¸ 4 2 | b | â¡ï¸ 5 3 | | [1, 2, 3] // waiting for GC 4 | | [5, 5] 5 | | { value: â¡ï¸4 }
Maintenant a
est initialisé, et un nouveau tableau est créé. Ce tableau n'est cependant pas stocké directement sous la variable, mais à un autre emplacement, à l'intérieur d'un a
il y a juste une référence à cet emplacement:
location | name² | value ------------------------------------- 1 | a | â¡ï¸ 4 2 | b | â¡ï¸ 3 3 | | [1, 2, 3] 4 | | [5, 5]
Maintenant, lorsque vous faites b = a
la référence est copiée, vous vous retrouvez à:
location | name² | value ------------------------------------- 1 | a | â¡ï¸ 3 2 | b | â¡ï¸ 3 3 | | [1, 2, 3]
Maintenant, lorsque vous faites a = [ 5,5]
un autre tableau est créé, et a
y fait référence. Cependant, b
n'a pas été modifié, il fait toujours référence à l'autre tableau.
location | name² | value ------------------------------------- 1 | a | â¡ï¸ 3 2 | b | undefined 3 | | [1, 2, 3]
Ou si vous faites b = {value: a}
:
location | name² | value ------------------------------------- 1 | a | undefined 2 | b | undefined
¹ oui, JavaScript est un langage interprété, vous ne saurez donc pas avec certitude comment il se retrouve dans la mémoire à la fin, c'est au moteur. Cependant, JS dérive ses concepts d'autres langages, et c'est pourquoi il est souvent utile de penser à un bas niveau.
² il n'y a pas de nom d'un emplacement mémoire spécifique, j'ai juste ajouté que pour plus de clarté.
La visualisation est très cool. Pourriez-vous étendre cela en incluant également un cas où, par exemple, b = {value: a}
, ou tout autre scénario?
@donJoe "tout autre scénario" sera trop.
Il peut être utile de considérer les "variables" comme distinctes des "valeurs".
a
et b
dans votre exemple sont des variables.
[1,2,3]
, 4
et [5,5]
dans votre exemple sont des valeurs.
Plusieurs variables peuvent référencer la même valeur. Si cette valeur change (mute), toutes les variables qui font référence à cette valeur renverront la valeur modifiée. L'exemple ci-dessous définit les références de a
et b
à la même valeur, puis apporte des modifications à cette valeur via à la fois la référence de a
et le référence de b
. Le résultat est que la valeur modifiée est toujours référencée par les deux variables.
var a = [1,2,3]; // a references the value [1,2,3] var b = a; // b references the value [1,2,3] a = [5,5]; // a reference assigned to new value [5,5] console.log(a); // [5,5] console.log(b); // [1,2,3]
Cependant, vous pouvez changer la valeur à laquelle une variable fait référence en la "affectant" à une nouvelle valeur. Cela ne changera pas (mute) la valeur elle-même et ne changera pas la référence de toute autre variable ayant fait référence à la même valeur. L'exemple ci-dessous définit les références de a
et b
à la même valeur, puis change la référence de a
en une nouvelle valeur. Le résultat est que les variables font désormais référence à des valeurs différentes.
var a = [1,2,3]; // a references the value [1,2,3] var b = a; // b references the value [1,2,3] a[0] = 4; // [1,2,3] changed to [4,2,3] b[1] = 5; // [1,2,3] changed to [4,5,3] console.log(a); // [4,5,3] console.log(b); // [4,5,3]
Ce que Tyler a dit et la journalisation de la console afficheront les éléments tels qu'ils sont, et non tels qu'ils étaient à l'avenir lorsque vous vous connecterez peut-être faire un
console.log (JSON.stringify (quelque chose, null, 2))
au lieu. Lorsque vous exécutez cevar arr = [{name: 'original'}]; console.log (arr); arr [0] .name = 'changed'
puis développez la sortie de la console, il dira "changé" mais vous l'avez connecté avant de le modifier.