Mes 2 Cents.... C'est ainsi que je le comprends. (N'hésitez pas à me corriger si je me trompe)
Il est temps de jeter tout ce que vous savez sur le passage par valeur / référence. Parce qu'en Javascript, cela n'a pas d'importance si c'est passé par valeur ou par référence ou autre.
Ce qui compte, c'est la mutation par rapport à l'affectation des paramètres passés dans une fonction.
OK, laissez-moi faire de mon mieux pour expliquer ce que je veux dire. Disons que vous avez quelques objets.
var object1 = {};
var object2 = {};
Ce que nous avons fait est une "affectation"... Nous avons assigné 2 objets vides distincts aux variables "object1" et "object2".
Maintenant, disons que nous préférons l'objet 1... Donc, nous "assignons" une nouvelle variable.
var favoriteObject = object1;
Ensuite, pour une raison quelconque, nous décidons que nous préférons l'objet 2. Donc, nous faisons simplement une petite réaffectation.
favoriteObject = object2;
Rien n'est arrivé à l'objet1 ou à l'objet2. Nous n'avons changé aucune donnée du tout. Tout ce que nous avons fait, c'est réassigner ce qu'est notre objet préféré. Il est important de savoir que object2 et favoriteObject sont tous deux affectés au même objet. Nous pouvons modifier cet objet via l'une ou l'autre de ces variables.
object2.name = 'Fred';
console.log(favoriteObject.name) // logs Fred
favoriteObject.name = 'Joe';
console.log(object2.name); // logs Joe
OK, maintenant regardons les primitives comme les chaînes de caractères par exemple.
var string1 = 'Hello world';
var string2 = 'Goodbye world';
Encore une fois, nous choisissons un favori.
var favoriteString = string1;
Nos deux variables favoriteString et string1 sont affectées à 'Hello world'. Maintenant, que se passe-t-il si nous voulons changer notre favoriteString ? ?? Que se passera-t-il ?
favoriteString = 'Hello everyone';
console.log(favoriteString); // Logs 'Hello everyone'
console.log(string1); // Logs 'Hello world'
Uh oh.... Ce qui s'est passé. Nous n'avons pas pu changer la chaîne 1 en changeant la chaîne favorite... Pourquoi ? parce que les chaînes de caractères sont immuables et que nous ne l'avons pas mutée. Tout ce que nous avons fait est de "RE ASSIGNER" favoriteString à une nouvelle chaîne. Cela l'a essentiellement déconnectée de string1. Dans l'exemple précédent, lorsque nous avons renommé notre objet, nous n'avons rien assigné. Au lieu de cela, nous avons simplement muté l'objet, ce qui maintient les connexions entre les deux variables et les objets sous-jacents.
Maintenant, passons aux fonctions et au passage des paramètres.... Lorsque vous appelez une fonction et que vous lui passez un paramètre, vous effectuez essentiellement une "affectation" à une nouvelle variable, et cela fonctionne exactement de la même manière que si vous aviez simplement affecté en utilisant le signe égal (=).
Prenez ces exemples.
var myString = 'hello';
// Assign to a new variable (just like when you pass to a function)
var param1 = myString;
param1 = 'world'; // Re assignment
console.log(myString); // logs 'hello'
console.log(param1); // logs 'world'
Maintenant, la même chose, mais avec une fonction
function myFunc(param1) {
param1 = 'world';
}
var myString = 'hello';
// Calls myFunc and assigns param1 to myString just like param1 = myString
myFunc(myString);
console.log(myString); // logs 'hello'
console.log(param1); // logs 'world'
OK, maintenant donnons quelques exemples en utilisant des objets à la place... d'abord, sans la fonction.
var myObject = {
firstName: 'Joe',
lastName: 'Smith'
};
// Assign to a new variable (just like when you pass to a function)
var otherObj = myObject;
// Let's mutate our object
otherObj.firstName = 'Sue'; // I guess Joe decided to be a girl
console.log(myObject.firstName); // Logs 'Sue'
console.log(otherObj.firstName); // Logs 'Sue'
// Now, let's reassign
otherObj = {
firstName: 'Jack',
lastName: 'Frost'
};
// Now, otherObj and myObject are assigned to 2 very different objects
// And mutating one object no longer mutates the other
console.log(myObject.firstName); // Logs 'Sue'
console.log(otherObj.firstName); // Logs 'Jack';
Maintenant, la même chose, mais avec un appel de fonction
function myFunc(otherObj) {
// Let's mutate our object
otherObj.firstName = 'Sue';
console.log(otherObj.firstName); // Logs 'Sue'
// Now let's re-assign
otherObj = {
firstName: 'Jack',
lastName: 'Frost'
};
console.log(otherObj.firstName); // Logs 'Jack'
// Again, otherObj and myObject are assigned to 2 very different objects
// And mutating one object no longer mutates the other
}
var myObject = {
firstName: 'Joe',
lastName: 'Smith'
};
// Calls myFunc and assigns otherObj to myObject just like otherObj = myObject
myFunc(myObject);
console.log(myObject.firstName); // Logs 'Sue', just like before
OK, si vous avez lu l'intégralité de cet article, vous avez peut-être maintenant une meilleure compréhension du fonctionnement des appels de fonction en javascript. Peu importe si quelque chose est passé par référence ou par valeur... Ce qui compte c'est l'assignation vs la mutation.
Chaque fois que vous passez une variable à une fonction, vous "affectez" le nom de la variable du paramètre, comme si vous utilisiez le signe égal (=).
N'oubliez jamais que le signe égal (=) signifie une affectation. N'oubliez jamais que le fait de passer un paramètre à une fonction signifie également une affectation. C'est la même chose et les 2 variables sont reliées exactement de la même manière.
La seule fois où la modification d'une variable affecte une autre variable est lorsque l'objet sous-jacent est muté.
Il est inutile de faire une distinction entre les objets et les primitives, car cela fonctionne exactement de la même manière que si vous n'aviez pas de fonction et que vous utilisiez simplement le signe égal pour assigner à une nouvelle variable.
Le seul problème est que le nom de la variable que vous passez dans la fonction est le même que le nom du paramètre de la fonction. Dans ce cas, vous devez traiter le paramètre dans la fonction comme s'il s'agissait d'une toute nouvelle variable privée à la fonction (car c'est le cas).
function myFunc(myString) {
// myString is private and does not affect the outer variable
myString = 'hello';
}
var myString = 'test';
myString = myString; // Does nothing, myString is still 'test';
myFunc(myString);
console.log(myString); // logs 'test'