parameter - pass by reference javascript
Alcance en javascript actuando raro (6)
Los objetos se pasan con su referencia en javascript. El significado de cambio en ese objeto desde cualquier lugar debe ser reflejado. En este caso, el resultado esperado fue {} para console.log (a)
function change(a,b) {
a.x = ''added'';
a = b;//assigning a as {} to b
}
a={}
b={}
change(a,b);
console.log(a); //expected {} but output {x:''added''}
console.log(b)
¿Que está sucediendo aquí? No debería ser por el alcance funcional que yo sepa. Gracias
Los objetos se pasan con su referencia en javascript.
No, no lo son. ECMAScript / JavaScript es estrictamente pasado por valor. (Más precisamente, llamada por uso compartido, que es un caso especial de paso por valor).
¿Que está sucediendo aquí?
Esto es simplemente el paso por valor normal.
Su confusión se debe al hecho de que, erróneamente, cree que ECMAScript / JavaScript es paso por referencia, cuando en realidad no lo es.
ECMAScript usa paso por valor, o más precisamente, un caso especial de paso por valor donde el valor que se pasa siempre es un puntero. Este caso especial también se conoce a veces como llamada por compartir, llamada por objeto compartido o llamada por objeto.
Es la misma convención utilizada por Java (para objetos), C # (por defecto para tipos de referencia), Smalltalk, Python, Ruby y más o menos todos los lenguajes orientados a objetos jamás creados.
Nota: algunos tipos (por ejemplo, Number
s) en realidad se pasan directamente por valor y no con un puntero intermedio. Sin embargo, dado que estos son inmutables, no hay una diferencia de comportamiento observable entre paso por valor y llamada por objeto en este caso, por lo que puede simplificar enormemente su modelo mental simplemente tratando todo como llamada por objeto. compartiendo Simplemente interprete estos casos especiales como optimizaciones internas del compilador de las que no tienes que preocuparte.
Este es un ejemplo simple que puede ejecutar para determinar la convención de aprobación de argumentos de ECMAScript (o cualquier otro idioma, después de traducirlo):
function isEcmascriptPassByValue(foo) {
foo.push(''More precisely, it is call-by-object-sharing!'');
foo = ''No, ECMAScript is pass-by-reference.'';
return;
}
var bar = [''Yes, of course, ECMAScript *is* pass-by-value!''];
isEcmascriptPassByValue(bar);
console.log(bar);
// Yes, of course, ECMAScript *is* pass-by-value!,
// More precisely, it is call-by-object-sharing!
Si está familiarizado con C #, es una muy buena manera de entender las diferencias entre el paso por valor y el paso por referencia para los tipos de valor y los tipos de referencia, porque C # es compatible con las 4 combinaciones: paso por valor para el valor tipos ("paso por valor tradicional"), paso por valor para tipos de referencia (llamada por compartir, llamada por objeto, llamada por objeto compartido como en ECMAScript), paso por referencia para tipos de referencia y paso por referencia para tipos de valor.
(En realidad, incluso si no conoces C #, esto no es demasiado difícil de seguir).
// In C#, struct defines a value type, class defines a reference type
struct MutableCell
{
public string value;
}
class Program
{
// the ref keyword means pass-by-reference, otherwise it''s pass-by-value
// You must explicitly request pass-by-reference both at the definition and the call
static void IsCSharpPassByValue(string[] foo, MutableCell bar, ref string baz, ref MutableCell qux)
{
foo[0] = "More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.";
foo = new string[] { "C# is not pass-by-reference." };
bar.value = "For value types, it is *not* call-by-sharing.";
bar = new MutableCell { value = "And also not pass-by-reference." };
baz = "It also supports pass-by-reference if explicitly requested.";
qux = new MutableCell { value = "Pass-by-reference is supported for value types as well." };
}
static void Main(string[] args)
{
var quux = new string[] { "Yes, of course, C# *is* pass-by-value!" };
var corge = new MutableCell { value = "For value types it is pure pass-by-value." };
var grault = "This string will vanish because of pass-by-reference.";
var garply = new MutableCell { value = "This string will vanish because of pass-by-reference." };
// the first two are passed by value, the other two by reference
IsCSharpPassByValue(quux, corge, ref grault, ref garply);
Console.WriteLine(quux[0]);
// More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.
Console.WriteLine(corge.value);
// For value types it is pure pass-by-value.
Console.WriteLine(grault);
// It also supports pass-by-reference if explicitly requested.
Console.WriteLine(garply.value);
// Pass-by-reference is supported for value types as well.
}
}
Bien, entonces has descubierto que los objetos de JavaScript tienen una semántica de referencia, por lo que la modificación de un referente tiene un efecto en el mismo objeto en el ámbito original.
Lo que también debe darse cuenta es que =
no es parte de estas reglas; no solo realiza la asignación, sino que también vuelve a enlazar la referencia a un nuevo objeto.
Bajo el capó, por así decirlo, así es como se formaron sus referencias originales.
Esto debería ayudar a resolver su problema:
var obj = {}, anotherObj = {};
// in case if they are not global, make them global or define parent scope to be able to modify inside the function
window.obj = obj;
window.anotherObj = anotherObj;
function swap(a, b) {
window[a].newProp = ''XYZ'';
window[a] = window[b]; // now obj is gone, because replaced with anotherObj
}
swap(''obj'',''anotherObj'');
console.log(obj); // now it would give Object {}
La variable ''a'' en el contexto de su función no es la misma que la variable ''a'' fuera de la función. Este código es semánticamente equivalente al tuyo:
function change(foo,bar) {
foo.x = ''added'';
foo = bar;//assigning foo as {} to bar
}
a={}
b={}
change(a,b);
console.log(a); //expected {} but output {x:''added''}
console.log(b)
En este caso, es obvio que la variable ''foo'' solo existe dentro de la función, y hacer foo = bar
no cambia a
ya que la referencia se pasa por valor.
Si agregó otra línea, puede obtener una imagen más clara de lo que está sucediendo:
function change(a,b) {
a.x = ''added'';
a = b;
a.x = ''added as well'';
};
a={};
b={};
change(a,b);
console.log(a); //{x:''added''}
console.log(b); //{x:''added as well''}
Cuando estás haciendo a = b
, estás asignando la variable local a la referencia que b
contiene.
Tiene razón en que los objetos se pasan por referencia y cualquier cambio realizado en el objeto en la función se reflejará en todas partes. Esta es precisamente la razón por la que agregar la propiedad x
en la función modificó el objeto fuera de ella.
Lo que te falta es que la línea a = b;
no modifica el objeto , modifica la referencia al objeto . Puede pasar los dos objetos en otro objeto contenedor / matriz si necesita establecer la referencia:
function change(container) {
container.a.x = ''added'';
container.a = container.b;//assigning a as {} to b
}
var container = { a: {}, b: {}};
change(container);
console.log(container.a);
console.log(container.b)