Mis dos centavos ... Así es como lo entiendo. (Siéntase libre de corregirme si me equivoco)
Es hora de tirar todo lo que sabe sobre pasar por valor / referencia.
Porque en JavaScript, no importa si se pasa por valor o por referencia o lo que sea. Lo que importa es la mutación frente a la asignación de los parámetros pasados a una función.
OK, déjame hacer todo lo posible para explicar lo que quiero decir. Digamos que tienes algunos objetos.
var object1 = {};
var object2 = {};
Lo que hemos hecho es "asignación" ... Hemos asignado 2 objetos vacíos separados a las variables "objeto1" y "objeto2".
Ahora, digamos que nos gusta mejor object1 ... Entonces, "asignamos" una nueva variable.
var favoriteObject = object1;
A continuación, por cualquier motivo, decidimos que nos gusta más el objeto 2. Entonces, simplemente hacemos una pequeña reasignación.
favoriteObject = object2;
No le pasó nada al objeto1 ni al objeto2. No hemos cambiado ningún dato en absoluto. Todo lo que hicimos fue reasignar cuál es nuestro objeto favorito. Es importante saber que object2 y favoriteObject están asignados al mismo objeto. Podemos cambiar ese objeto a través de cualquiera de esas variables.
object2.name = 'Fred';
console.log(favoriteObject.name) // Logs Fred
favoriteObject.name = 'Joe';
console.log(object2.name); // Logs Joe
OK, ahora veamos primitivas como cadenas por ejemplo
var string1 = 'Hello world';
var string2 = 'Goodbye world';
De nuevo, elegimos un favorito.
var favoriteString = string1;
Nuestras variables favoriteString y string1 se asignan a 'Hello world'. Ahora, ¿qué pasa si queremos cambiar nuestra cadena favorita? ¿¿¿Lo que sucederá???
favoriteString = 'Hello everyone';
console.log(favoriteString); // Logs 'Hello everyone'
console.log(string1); // Logs 'Hello world'
Uh oh ... lo que ha pasado. No pudimos cambiar string1 cambiando a favoriteString ... ¿Por qué? Porque no cambiamos nuestro objeto de cadena . Todo lo que hicimos fue "RE ASIGNAR" la variable favoriteString a una nueva cadena. Esto esencialmente lo desconectó de la cadena1. En el ejemplo anterior, cuando cambiamos el nombre de nuestro objeto, no asignamos nada. (Bueno, no a la variable en sí , ... sin embargo, asignamos la propiedad de nombre a una nueva cadena.) En cambio, simplemente mutamos el objeto que mantiene las conexiones entre las 2 variables y los objetos subyacentes. (Incluso si hubiéramos querido modificar o mutar el objeto de cadena en sí, no podríamos haberlo hecho, porque las cadenas son realmente inmutables en JavaScript).
Ahora, a las funciones y a pasar parámetros ... Cuando llamas a una función y pasas un parámetro, lo que estás haciendo esencialmente es una "asignación" a una nueva variable, y funciona exactamente igual que si simplemente te asignaras usando el signo igual (=)
Toma estos ejemplos.
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'
Ahora, lo mismo, pero con una función
function myFunc(param1) {
param1 = 'world';
console.log(param1); // Logs 'world'
}
var myString = 'hello';
// Calls myFunc and assigns param1 to myString just like param1 = myString
myFunc(myString);
console.log(myString); // logs 'hello'
Bien, ahora demos algunos ejemplos usando objetos en su lugar ... primero, sin la función.
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 the variable
otherObj = {
firstName: 'Jack',
lastName: 'Frost'
};
// Now, otherObj and myObject are assigned to 2 very different objects
// And mutating one object has no influence on the other
console.log(myObject.firstName); // Logs 'Sue'
console.log(otherObj.firstName); // Logs 'Jack';
Ahora, lo mismo, pero con una llamada a función
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 doesn't magically mutate 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 lees toda esta publicación, quizás ahora comprendas mejor cómo funcionan las llamadas a funciones en JavaScript. No importa si algo se pasa por referencia o por valor ... Lo que importa es la asignación frente a la mutación.
Cada vez que pasa una variable a una función, está "Asignando" a cualquiera que sea el nombre de la variable del parámetro, al igual que si usara el signo igual (=).
Recuerde siempre que el signo igual (=) significa asignación. Recuerde siempre que pasar un parámetro a una función en JavaScript también significa asignación. Son las mismas y las 2 variables están conectadas exactamente de la misma manera (es decir, no lo son, a menos que cuente que están asignadas al mismo objeto).
El único momento en que "modificar una variable" afecta a una variable diferente es cuando el objeto subyacente está mutado (en cuyo caso no ha modificado la variable, sino el objeto en sí).
No tiene sentido hacer una distinción entre objetos y primitivas, porque funciona de la misma manera que si no tuviera una función y solo utilizara el signo igual para asignar a una nueva variable.
El único problema es cuando el nombre de la variable que pasa a la función es el mismo que el nombre del parámetro de la función. Cuando esto sucede, debe tratar el parámetro dentro de la función como si fuera una variable completamente nueva y privada para la función (porque lo es)
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'