JavaScript n'a pas de "passage par référence vs.
Je montrerai pourquoi le folklore selon lequel "les objets JS sont passés par référence, les primitives sont passées par valeur" n'a rien à voir avec le passage, les objets, ni les références et est en fait une illusion. « Les objets sont passés par référence » (OAPBR) est un modèle théorique/mental. Comme la plupart des théories, elle doit être jugée sur sa contribution à la compréhension, à la prédiction, au contrôle, et sur son coût en termes de complexité. J'espère utiliser cet exemple comme preuve qu'un modèle mental très incorrect :
- Rend l'apprentissage des fonctionnalités avancées plus difficile
- Rend l'apprentissage d'autres langages de programmation plus difficile
- Et fait perdre du temps. À la fin, je ferai des suggestions pour éviter les modèles mentaux très incorrects.
Pour montrer ce que la théorie des « objets sont passés par référence » (OAPBR) cherche à expliquer, nous aurons d'abord besoin de deux définitions :
function plusNum(n1, n2) {
return n1 + n2;
}
function mutatingAdd(obj1, n) {
obj1.value = plusNum(obj1.value, n)
}
function takeNum(n /* number */) {
n = plusNum(n, 1);
console.log(n); // 2
}
function primitiveExample() {
let x = 1;
takeNum(x);
console.log(x); // 1
}
function mutateObj(obj /* {field: number} */) {
mutatingAdd(obj, 1);
console.log(obj.value); // 2
}
function objectExample() {
let x = {value: 1};
mutateObj(x);
console.log(x.value); // 2
}
Comment la théorie des « objets sont passés par référence » (OAPBR) échoue
Maintenant, je vais montrer que les exemples précédents n'ont rien à voir avec le passage de valeurs à des fonctions en adaptant les exemples pour ne pas utiliser de fonctions :
function primitiveExample2() {
let x = 1;
let y = x;
y = y + 1;
console.log(y); // 2
console.log(x); // 1
}
function objectExample2() {
let x = { value: 1 };
let y = x;
y.value = y.value + 1;
console.log(y.value); // 2
console.log(x.value); // 2
}
function combinedExample1() {
let x = Object.assign(1, { value: 100 });
let y = x;
mutatingAdd(y, 100);
console.log(y.value); // 200
console.log(x.value); // 200
y = plusNum(y, 1);
console.log(y + 0); // 2
console.log(x + 0); // 1
}
function nonMutatingPlusObj(obj1, obj2) {
return { value: obj1.value + obj2.value };
}
function nonMutatingObjectExample() {
let x = {value: 100};
let y = x;
y = nonMutatingPlusObj(y, {value: 100})
console.log(y.value); // 200
console.log(x.value); // 100
}
<?php
function add_mut(&$i1, $i2) {
$i1 += $i2;
}
$x = 1;
add_mut($x, 1);
echo $x; // 2
?>
fn add_mut(i: &mut i32, i2: i32) {
*i = (*i) + i2;
}
fn main() {
let i = &mut 1;
add_mut(i, 1);
println!("{}", i); // 2
}
function makeRef(thing) {
return {value: thing};
}
function addMut(iRef, i2) {
iRef.value = iRef.value + i2;
}
let iRef = makeRef(1);
addMut(iRef, 1);
console.log(iRef.value); // 2
Une meilleure théorie
Au lieu de "Les objets sont passés par référence, les primitives sont passées par valeur", je suggère une meilleure distinction : entre la mutation d'une portée et la mutation d'une valeur. Dans JS, les portées sont des mappages modifiables des noms de variables aux valeurs.
let x = 1; // the scope maps x to 1
x = 2; // the scope maps x to 2
x += 1; // the scope maps x to 3
L'illusion du « passage par référence » survient probablement dans le contexte des fonctions, car chaque fonction introduit une nouvelle portée. Plus d'informations sur les portées dans MDN .
Dans le code ci-dessous, xpointez ysur le même objet, qui mutateObjmute. mutatingAddne modifie pas la portée, car dans JavaScript, les fonctions ne peuvent pas muter la portée, elles ne se ferment pas :
function objectExample() {
let x = {value: 1};
let y = x;
mutatingAdd(y, 1);
console.log(y.value); // 2
console.log(x.value); // 2
}
Pour JS, en particulier, comprendre que la portée est mutable est essentiel pour comprendre const-vs-let, l'observation, l'identité d'objet, les fermetures et l'écriture d'interfaces utilisateur. Et c'est un concept si simple par rapport à la distinction incorrecte « par valeur contre par référence ».
Et après
J'ai vu de mauvais modèles mentaux pour les langages de programmation provenir de ces sources :
- Ne pas utiliser de ressources d'apprentissage, mais plutôt plonger et essayer de programmer. Cela peut sembler rapide, mais je pense que c'est la voie lente à long terme.
- Apprendre à partir d'articles de blog ou de vidéos. (Je sais qu'il s'agit d'un article de blog : faites plus confiance à MDN qu'à tout ici.)
- En supposant que les fonctionnalités du langage de programmation sont évidentes. Rien n'est évident, surtout pas les variables, et il existe des variations surprenantes entre et au sein des langages de programmation quant à la façon dont les choses fonctionnent.
Bon piratage !
![Qu'est-ce qu'une liste liée, de toute façon? [Partie 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































