JavaScript non ha un "passa per riferimento vs.
Mostrerò perché il folklore secondo cui "gli oggetti JS vengono passati per riferimento, i primitivi vengono passati per valore" non ha nulla a che fare con il passaggio, gli oggetti, né i riferimenti ed è in realtà un'illusione. "Gli oggetti sono passati per riferimento" (OAPBR) è un modello teorico/mentale. Come la maggior parte delle teorie, dovrebbe essere giudicata in base al suo contributo alla comprensione, alla previsione, al controllo e al suo costo in termini di complessità. Spero di utilizzare questo esempio come prova che un modello mentale molto errato:
- Rende più difficile l'apprendimento delle funzionalità avanzate
- Rende più difficile l'apprendimento di altri linguaggi di programmazione
- E fa perdere tempo. Alla fine darò suggerimenti per evitare modelli mentali molto errati.
Per mostrare ciò che la teoria "Gli oggetti sono passati per riferimento" (OAPBR) cerca di spiegare, abbiamo bisogno prima di tutto di due definizioni:
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
}
Come la teoria "Gli oggetti vengono passati per riferimento" (OAPBR) fallisce
Ora mostrerò che gli esempi precedenti non hanno nulla a che fare con il passaggio di valori alle funzioni adattando gli esempi per non utilizzare le funzioni:
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
Una teoria migliore
Invece di "Gli oggetti sono passati per riferimento, le primitive sono passate per valore", suggerisco una distinzione migliore: tra mutare uno scope e mutare un valore. In JS, gli ambiti sono mappature mutabili dai nomi delle variabili ai valori.
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'illusione del "passare per riferimento" sorge probabilmente nel contesto delle funzioni perché ogni funzione introduce un nuovo ambito. Maggiori informazioni sugli ambiti in MDN .
Nel codice seguente, xe ypunta allo stesso oggetto, che mutateObjmuta. mutatingAddnon muta l'ambito, poiché in JavaScript le funzioni non possono mutare l'ambito non si chiudono:
function objectExample() {
let x = {value: 1};
let y = x;
mutatingAdd(y, 1);
console.log(y.value); // 2
console.log(x.value); // 2
}
Per JS, in particolare, capire che l'ambito è mutabile è essenziale per comprendere const-vs-let, shadowing, identità dell'oggetto, chiusure e scrivere interfacce utente. Ed è un concetto così semplice rispetto all'errata distinzione "per valore vs. per riferimento".
Qual è il prossimo
Ho visto cattivi modelli mentali per i linguaggi di programmazione provenire da queste fonti:
- Non utilizzare alcuna risorsa di apprendimento, ma immergersi e provare a programmare. Questo può sembrare veloce, ma penso che sia il percorso lento a lungo termine.
- Imparare da post di blog o video. (So che questo è un post sul blog: fidati di MDN più di ogni altra cosa qui.)
- Supponendo che le caratteristiche del linguaggio di programmazione siano ovvie. Nulla è ovvio, specialmente non le variabili, e c'è una variazione sorprendente tra e all'interno dei linguaggi di programmazione per come funzionano le cose.
Buon hackeraggio!

![Che cos'è un elenco collegato, comunque? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































