J'ai récemment rencontré une question intéressante: "Les valeurs en JS sont-elles passées par valeur ou par référence?"
Avant d'analyser ce problème, nous devons comprendre ce qu'on appelle la valeur et ce qui est appelé par référence. En informatique, cette partie est appelée stratégie d'évaluation. Il détermine comment les valeurs sont passées entre les variables, entre les paramètres réels et les paramètres formels lors de l'appel d'une fonction.
Passer par valeur vs. Passer par référence
L'appel par valeur est la stratégie d'évaluation la plus couramment utilisée: les paramètres formels d'une fonction sont des copies des paramètres réels passés lors de l'appel. La modification de la valeur d'un paramètre formel n'affectera pas le paramètre réel.
En passant par référence (appel par référence), les paramètres formels de la fonction reçoivent une référence implicite du paramètre réel, plutôt qu'une copie. Cela signifie que si la valeur du paramètre de fonction est modifiée, le paramètre réel sera également modifié. Les deux indiquent la même valeur.
Passer par référence rend le suivi des appels de fonction plus difficile et provoque parfois des bogues subtils.
Passer par valeur car les répliques sont clonées à chaque fois, les performances sont plus faibles pour certains types complexes. Les deux méthodes de passage des valeurs ont leurs propres problèmes.
Examinons d'abord un exemple C pour comprendre la différence entre le passage par valeur et référence:
La copie de code est la suivante:
void modify (int p, int * q)
{
p = 27; // passer p par valeur est une copie du paramètre réel a, seul p est modifié
* Q = 27; // Q est une référence à B, et les deux Q et B sont modifiés
}
int main ()
{
int a = 1;
int b = 1;
Modifier (a, & b); // un pass par valeur, b passe par référence,
// a n'a pas changé, b a changé
return (0);
}
Ici, nous pouvons voir:
A => Lorsque P est passé par valeur, la modification de la valeur du paramètre formel P n'affecte pas le paramètre réel A, P n'est qu'une copie de a.
b => q est passé par référence. Lors de la modification de la valeur du paramètre formel Q, il affecte également la valeur du paramètre réel b.
Explorez comment la valeur JS est passée
Le type de base de JS est passé par valeur.
La copie de code est la suivante:
var a = 1;
fonction foo (x) {
x = 2;
}
foo (a);
console.log (a); // toujours 1, non affecté par l'affectation de x = 2
Regardons l'objet:
La copie de code est la suivante:
var obj = {x: 1};
fonction foo (o) {
ox = 3;
}
foo (obj);
console.log (obj.x); // 3, modifié!
Expliquez O et OBJ sont le même objet, et O n'est pas une copie d'OBJ. Il n'est donc pas passé par valeur. Mais cela signifie-t-il que les objets JS sont passés par référence? Regardons les exemples suivants:
La copie de code est la suivante:
var obj = {x: 1};
fonction foo (o) {
O = 100;
}
foo (obj);
console.log (obj.x); // Toujours 1, OBJ n'a pas été modifié à 100.
S'il est transmis par référence, modifiant la valeur du paramètre formel O, il doit affecter le paramètre réel. Mais modifier la valeur de O ici n'affecte pas l'OBJ. Par conséquent, les objets en JS ne sont pas transmis par référence. Alors, comment passer la valeur de l'objet en js?
Passer l'appel en partageant
Pour être précis, les types de base en js sont passés par des valeurs, et les types d'objets sont passés par partage (appel par partage, également appelé par objet et partagé par objet). Il a d'abord été proposé par Barbara Liskov. Dans la langue Glu de 1974. Cette stratégie d'évaluation est utilisée dans Python, Java, Ruby, JS et d'autres langues.
Le point de cette stratégie est que lorsqu'une fonction transmet un argument, la fonction accepte une copie de la référence réelle de l'argument de l'objet (ni une copie de l'objet passé par valeur, ni une référence implicite transmise par référence). La différence entre l'informatique et le passage par référence est que l'affectation des paramètres de fonction dans une réussite partagée n'affectera pas la valeur du paramètre réel. Comme dans l'exemple suivant, la valeur d'Obj ne peut pas être modifiée en modifiant la valeur du paramètre formel o.
La copie de code est la suivante:
var obj = {x: 1};
fonction foo (o) {
O = 100;
}
foo (obj);
console.log (obj.x); // Toujours 1, OBJ n'a pas été modifié à 100.
Cependant, bien que la référence soit une copie, l'objet référencé est le même. Ils partagent le même objet, donc modifier la valeur d'attribut de l'objet paramètre formel affectera également la valeur d'attribut du paramètre réel.
La copie de code est la suivante:
var obj = {x: 1};
fonction foo (o) {
ox = 3;
}
foo (obj);
console.log (obj.x); // 3, modifié!
Pour les types d'objets, puisque l'objet est mutable, la modification de l'objet lui-même affectera le partage de la référence et de la copie de référence de l'objet. Pour les types de base, comme ils sont tous deux immuables, il n'y a pas de différence entre passer par le partage et passer par valeur (appel par valeur), donc les types de base JS sont tous les deux conformes au passage par valeur et conformément au passage par partage.
La copie de code est la suivante:
var a = 1; // 1 est le numéro de type, var immuable b = a; b = 6;
Selon la stratégie d'évaluation adoptée par partagée, A et B sont deux références différentes (B est une copie de référence de A), mais des références de la même valeur. Étant donné que le type de base numéro 1 ici est immuable, il n'y a pas de différence entre passer par valeur et passer par part ici.
Propriétés immuables des types de base
Les types de base sont immuables et seuls les objets sont mutables. Par exemple, les valeurs numériques 100, les valeurs booléennes sont vraies, fausses et modifiant ces valeurs (par exemple, transformer 1 en 3 et devenir vrai en 100) n'a pas de sens. Ce qui est plus facile à mal comprendre, c'est la chaîne en js. Parfois, nous essayons de "modifier" le contenu de la chaîne, mais dans JS, toute opération "modifier" qui semble être une valeur de chaîne crée en fait une nouvelle valeur de chaîne.
La copie de code est la suivante:
var str = «ABC»;
str [0]; // "un"
str [0] = "d";
Str; // Toujours "ABC"; L'attribution n'est pas valide. Il n'y a aucun moyen de modifier le contenu de la chaîne
L'objet est différent, l'objet est variable.
La copie de code est la suivante:
var obj = {x: 1};
obj.x = 100;
var o = obj;
ox = 1;
obj.x; // 1, modifié
o = true;
obj.x; // 1, ne changera pas en raison de o = vrai
Ici, la variable obj est définie, la valeur est objet, puis la valeur de la propriété obj.x est définie sur 100. Définissez ensuite une autre variable O, et la valeur est toujours cet objet. À l'heure actuelle, les valeurs des deux variables OBJ et O pointent vers le même objet (partageant une référence au même objet). Par conséquent, la modification du contenu de l'objet a un impact sur OBJ et O. Cependant, l'objet n'est pas passé par référence. La valeur d'O est modifiée par O = Vrai et n'affectera pas l'OBJ.