variable valor una tipos retornar referencia por pasar parametros otra funciones funcion desde dentro anonimas javascript pass-by-reference pass-by-value

javascript - una - valor por referencia js



¿Es JavaScript un lenguaje de paso por referencia o de paso por valor? (29)

Los tipos primitivos (Número, Cadena, etc.) se pasan por valor, pero los Objetos son desconocidos, ya que pueden pasarse por valor (en caso de que consideremos que una variable que contiene un objeto es de hecho una referencia al objeto ) y pasado por referencia (cuando consideramos que la variable del objeto contiene el objeto en sí).

Aunque realmente no importa al final, quiero saber cuál es la forma correcta de presentar los argumentos pasando las convenciones. ¿Hay un extracto de la especificación de JavaScript, que define lo que debería ser la semántica con respecto a esto?


compartiendo lo que sé de referencias en javascript

En Javascript, los objetos se almacenan como referencias:

var a = { a: 1, b: 2, c: 3 }; var b = a; //b.c is referencing to a.c value console.log(b.c) //output: 3 //changing value of b.c b.c = 4 //also changes the value of a.c console.log(a.c) //output: 4


JavaScript pasa tipos primitivos por valor y tipos de objeto por referencia

Ahora, a la gente le gusta discutir sin parar sobre si "pasar por referencia" es la forma correcta de describir lo que Java et al. en realidad hacer El punto es este:

  1. Pasar un objeto no copia el objeto.
  2. Un objeto pasado a una función puede tener sus miembros modificados por la función.
  3. Un valor primitivo pasado a una función no puede ser modificado por la función. Se hace una copia.

En mi libro que se llama pasar por referencia.

- Brian Bi - ¿Qué lenguajes de programación se pasan por referencia?


  1. Las primitivas (Number, Boolean) se pasan por valor.
    • Las cuerdas son inmutables, por lo que realmente no importa para ellas.
  2. Los objetos se pasan por referencia (la referencia se pasa por valor)

  1. Tipo de variable primitiva como cadena, el número siempre se pasa como pase por valor.
  2. La matriz y el objeto se pasan como paso por referencia o se pasan por valor en función de estas dos condiciones.

    • Si está cambiando el valor de ese objeto o matriz con un nuevo objeto o matriz, entonces se pasa por valor.

      object1 = {item: "car"}; array1=[1,2,3];

    Aquí está asignando un nuevo objeto o matriz a uno antiguo. No está cambiando el valor de la propiedad del objeto antiguo. Por lo tanto, se pasa por valor.

    • Si está cambiando el valor de una propiedad de un objeto o matriz, se pasa por Referencia.

      object1.key1= "car"; array1[0]=9;

    Aquí está cambiando un valor de propiedad del objeto antiguo. No está asignando un nuevo objeto o matriz a uno antiguo. Por lo tanto, se pasa por referencia.

Código

function passVar(object1, object2, number1) { object1.key1= "laptop"; object2 = { key2: "computer" }; number1 = number1 + 1; } var object1 = { key1: "car" }; var object2 = { key2: "bike" }; var number1 = 10; passVar(object1, object2, number1); console.log(object1.key1); console.log(object2.key2); console.log(number1); Output: - laptop bike 10


Considera lo siguiente:

  1. Las variables son punteros a valores en memoria.
  2. La reasignación de una variable simplemente apunta ese puntero a un nuevo valor.
  3. Reasignar una variable nunca afectará otras variables que apuntaban al mismo objeto

Entonces, olvídate de "pasar por referencia / valor" , no te cuelgues de "pasar por referencia / valor" porque:

  1. Los términos solo se usan para describir el comportamiento de un lenguaje, no necesariamente la implementación subyacente real. Como resultado de esta abstracción, los detalles críticos que son esenciales para una explicación decente se pierden, lo que inevitablemente conduce a la situación actual en la que un solo término no describe adecuadamente el comportamiento real y se debe proporcionar información adicional.
  2. Estos conceptos no se definieron originalmente con la intención de describir javascript en particular, por lo que no me siento obligado a usarlos cuando solo aumentan la confusión.

Para responder a tu pregunta: se pasan los punteros.


// code var obj = { name: ''Fred'', num: 1 }; // illustration ''Fred'' / / (obj) ---- {} / / 1


// code obj.name = ''George''; // illustration ''Fred'' (obj) ---- {} ----- ''George'' / / 1


// code obj = {}; // illustration ''Fred'' (obj) {} ----- ''George'' | / | / { } 1


// code var obj = { text: ''Hello world!'' }; /* function parameters get their own pointer to * the arguments that are passed in, just like any other variable */ someFunc(obj); // illustration (caller scope) (someFunc scope) / / / / / / / / / / { } | | | ''Hello world''

Algunos comentarios finales:

  • Es tentador pensar que las primitivas se aplican mediante reglas especiales mientras que los objetos no lo son, pero las primitivas son simplemente el final de la cadena de punteros.
  • Como ejemplo final, considere por qué un intento común de borrar una matriz no funciona como se esperaba.


var a = [1,2]; var b = a; a = []; console.log(b); // [1,2] // doesn''t work because `b` is still pointing at the original array


El objeto fuera de una función se pasa a una función dando una referencia al objeto externo. Cuando utiliza esa referencia para manipular su objeto, el objeto externo se ve afectado. Sin embargo, si dentro de la función usted decidió apuntar la referencia a otra cosa, no afectó al objeto externo en absoluto, porque todo lo que hizo fue redirigir la referencia a otra cosa.


En este capítulo del libro "JavaScript: la guía definitiva", encontrará una explicación muy detallada sobre cómo copiar, pasar y comparar por valor y por referencia.

Antes de dejar el tema de la manipulación de objetos y matrices por referencia, debemos aclarar un punto de nomenclatura. La frase "pasar por referencia" puede tener varios significados. Para algunos lectores, la frase se refiere a una técnica de invocación de función que permite que una función asigne nuevos valores a sus argumentos y tenga esos valores modificados visibles fuera de la función. Esta no es la forma en que se usa el término en este libro. Aquí, queremos decir simplemente que una referencia a un objeto o matriz, no el objeto en sí, se pasa a una función. Una función puede usar la referencia para modificar las propiedades del objeto o elementos de la matriz. Pero si la función sobrescribe la referencia con una referencia a un nuevo objeto o matriz, esa modificación no es visible fuera de la función. Los lectores familiarizados con el otro significado de este término pueden preferir decir que los objetos y las matrices se pasan por valor, pero el valor que se pasa es en realidad una referencia en lugar del objeto en sí.

Una cosa que todavía no puedo entender. Compruebe el código a continuación. ¿Alguna idea?

function A() {} A.prototype.foo = function() { return ''initial value''; } function B() {} B.prototype.bar = A.prototype.foo; console.log(A.prototype.foo()); //initial value console.log(B.prototype.bar()); //initial value A.prototype.foo = function() { return ''changed now''; } console.log(A.prototype.foo()); //changed now console.log(B.prototype.bar()); //Why still ''initial value''???


En JavaScript, el tipo de valor solo controla si ese valor se asignará mediante copia de valor o copia de referencia .

Los valores primitivos siempre se asignan / pasan por copia de valor :

  • null
  • undefined
  • cuerda
  • número
  • booleano
  • símbolo en ES6

Los valores compuestos siempre se asignan / pasan por referencia-copia

  • objetos
  • matrices
  • función

Por ejemplo

var a = 2; var b = a; // `b` is always a copy of the value in `a` b++; a; // 2 b; // 3 var c = [1,2,3]; var d = c; // `d` is a reference to the shared `[1,2,3]` value d.push( 4 ); c; // [1,2,3,4] d; // [1,2,3,4]

En el fragmento de código anterior, porque 2 es una primitiva escalar, a contiene una copia inicial de ese valor, b se asigna otra copia del valor. Al cambiar b , de ninguna manera está cambiando el valor en a .

Pero tanto c como d son referencias separadas al mismo valor compartido [1,2,3] , que es un valor compuesto. Es importante tener en cuenta que ni c ni d más "poseen" el valor [1,2,3] ; ambos son solo referencias iguales al valor. Por lo tanto, al usar cualquiera de las dos referencias para modificar ( .push(4) ) el valor real de la array compartida, afecta solo al valor compartido, y ambas referencias harán referencia al valor recientemente modificado [1,2,3,4] .

var a = [1,2,3]; var b = a; a; // [1,2,3] b; // [1,2,3] // later b = [4,5,6]; a; // [1,2,3] b; // [4,5,6]

Cuando hacemos la asignación b = [4,5,6] , no estamos haciendo absolutamente nada para afectar a donde a todavía se hace referencia ( [1,2,3] ). Para hacer eso, b tendría que ser un puntero a una referencia en lugar de una referencia a la array , ¡pero no existe tal capacidad en JS!

function foo(x) { x.push( 4 ); x; // [1,2,3,4] // later x = [4,5,6]; x.push( 7 ); x; // [4,5,6,7] } var a = [1,2,3]; foo( a ); a; // [1,2,3,4] not [4,5,6,7]

Cuando pasamos el argumento a , asigna una copia de a referencia a x . x y a son referencias separadas que apuntan al mismo valor [1,2,3] . Ahora, dentro de la función, podemos usar esa referencia para mutar el valor en sí ( push(4) ). Pero cuando hacemos la asignación x = [4,5,6] , esto no afecta de ninguna manera a dónde está apuntando la referencia inicial a - todavía apunta al valor (ahora modificado) [1,2,3,4] .

Para pasar efectivamente un valor compuesto (como una array ) por copia de valor, necesita hacer una copia manualmente, para que la referencia pasada no apunte al original. Por ejemplo:

foo( a.slice() );

Valor compuesto (objeto, matriz, etc.) que se puede pasar por copia de referencia

function foo(wrapper) { wrapper.a = 42; } var obj = { a: 2 }; foo( obj ); obj.a; // 42

Aquí, obj actúa como un envoltorio para la propiedad primitiva escalar a . Cuando se pasa a foo(..) , se pasa una copia de la referencia obj y se establece en el parámetro de wrapper . Ahora podemos usar la referencia del wrapper para acceder al objeto compartido y actualizar su propiedad. Una vez que finalice la función, obj.a verá el valor actualizado 42 .

Source


Es interesante en Javascript. Considera este ejemplo:

function changeStuff(a, b, c) { a = a * 10; b.item = "changed"; c = {item: "changed"}; } var num = 10; var obj1 = {item: "unchanged"}; var obj2 = {item: "unchanged"}; changeStuff(num, obj1, obj2); console.log(num); console.log(obj1.item); console.log(obj2.item);

Esto produce la salida:

10 changed unchanged

  • Si fuera pura pasada por valor, el cambio de obj1.item no tendría efecto en el obj1 fuera de la función.
  • Si fuera pura pasada por referencia, entonces todo habría cambiado. num sería 100 y obj2.item se leería "changed" .

En cambio, la situación es que el elemento pasado se pasa por valor. Pero el elemento que se pasa por valor es en sí mismo una referencia. Técnicamente, esto se llama call-by-sharing .

En términos prácticos, esto significa que si cambia el parámetro en sí (como con num y obj2 ), eso no afectará al elemento que se introdujo en el parámetro. Pero si cambia los INTERNOS del parámetro, eso se propagará de nuevo (como en obj1 ).


Javascript siempre se pasa por valor , todo es de tipo valor. Los objetos son valores, las funciones miembro de los objetos son valores en sí mismos (recuerde que las funciones son objetos de primera clase en Javascript). Además, con respecto al concepto de que todo en Javascript es un objeto , esto está mal. Cadenas, símbolos, números, valores booleanos, nulos e indefinidos son primitivos . En ocasiones, pueden aprovechar algunas de las funciones y propiedades de los miembros heredadas de sus prototipos básicos, pero esto es solo por conveniencia, no significa que sean objetos en sí mismos. Prueba lo siguiente para referencia

x = "test"; alert(x.foo); x.foo = 12; alert(x.foo);

En ambas alertas encontrará que el valor no está definido.


La variable no "mantiene" el objeto, tiene una referencia. Puede asignar esa referencia a otra variable, ahora ambas hacen referencia al mismo objeto. Siempre se pasa por valor (incluso cuando ese valor es una referencia ...).

No hay manera de alterar el valor mantenido por una variable pasada como parámetro, lo que sería posible si JS admitiera el paso por referencia.


Mis 2 centavos .... Esta es la forma en que lo entiendo. (Siéntete libre de corregirme si me equivoco)

Es hora de desechar todo lo que sabe sobre el paso 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 mi mejor esfuerzo 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 object1 mejor ... Entonces, "asignamos" una nueva variable.

var favoriteObject = object1;

A continuación, por el motivo que sea, decidimos que nos gusta más el objeto 2. Por lo tanto, simplemente hacemos una pequeña re-asignación.

favoriteObject = object2;

Nada le pasó a object1 o a object2. No hemos cambiado ningún dato. 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'';

Una vez más, elegimos un favorito.

var favoriteString = string1;

Tanto nuestras variables favoriteString como string1 están asignadas a ''Hello world''. Ahora, ¿y 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 ... ¿Qué ha pasado? No pudimos cambiar string1 cambiando favoriteString ... ¿Por qué? Porque las cuerdas son inmutables y no las mutamos. Todo lo que hicimos fue "RE ASSIGN" favoriteString a una nueva cadena. Esto esencialmente lo desconectó de string1. En el ejemplo anterior, cuando cambiamos el nombre de nuestro objeto, no asignamos nada. (Bueno, en realidad ... lo hicimos, 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.

Ahora, con las funciones y los parámetros de paso ... Cuando llama a una función y pasa un parámetro, lo que está haciendo esencialmente es "asignación" a una nueva variable, y funciona exactamente igual que si simplemente lo asignara usando la signo igual (=).

Tomemos 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 vamos a dar 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 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'';

Ahora, lo mismo, pero con una función llamada.

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

De acuerdo, si leyó esta publicación completa, tal vez ahora tenga una mejor comprensión de 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 de parámetro, como si usara el signo igual (=).

Recuerde siempre que el signo igual (=) significa asignación. Siempre recuerde que pasar un parámetro a una función también significa asignación. Son iguales y las 2 variables están conectadas exactamente de la misma manera.

La única vez que la modificación de una variable afecta a una variable diferente es cuando se muta el objeto subyacente.

No tiene sentido hacer una distinción entre objetos y primitivos, porque funciona de la misma manera que si no tuviera una función y solo usara el signo igual para asignarlo a una nueva variable.

La única respuesta es cuando el nombre de la variable que se 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 a 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''


Pasar argumentos a una función en JavaScript es análogo a pasar parámetros por valor de puntero en C:

/* The following C program demonstrates how arguments to JavaScript functions are passed in a way analogous to pass-by-pointer-value in C. The original JavaScript test case by @Shog9 follows with the translation of the code into C. This should make things clear to those transitioning from C to JavaScript. function changeStuff(num, obj1, obj2) { num = num * 10; obj1.item = "changed"; obj2 = {item: "changed"}; } var num = 10; var obj1 = {item: "unchanged"}; var obj2 = {item: "unchanged"}; changeStuff(num, obj1, obj2); console.log(num); console.log(obj1.item); console.log(obj2.item); This produces the output: 10 changed unchanged */ #include <stdio.h> #include <stdlib.h> struct obj { char *item; }; void changeStuff(int *num, struct obj *obj1, struct obj *obj2) { // make pointer point to a new memory location // holding the new integer value int *old_num = num; num = malloc(sizeof(int)); *num = *old_num * 10; // make property of structure pointed to by pointer // point to the new value obj1->item = "changed"; // make pointer point to a new memory location // holding the new structure value obj2 = malloc(sizeof(struct obj)); obj2->item = "changed"; free(num); // end of scope free(obj2); // end of scope } int num = 10; struct obj obj1 = { "unchanged" }; struct obj obj2 = { "unchanged" }; int main() { // pass pointers by value: the pointers // will be copied into the argument list // of the called function and the copied // pointers will point to the same values // as the original pointers changeStuff(&num, &obj1, &obj2); printf("%d/n", num); puts(obj1.item); puts(obj2.item); return 0; }


Piénselo así: siempre se pasa por valor. Sin embargo, el valor de un objeto no es el objeto en sí, sino una referencia a ese objeto.

Aquí hay un ejemplo, pasando un número (un tipo primitivo)

function changePrimitive(val) { // At this point there are two ''10''s in memory. // Changing one won''t affect the other val = val * 10; } var x = 10; changePrimitive(x); // x === 10

Repitiendo esto con un objeto produce diferentes resultados:

function changeObject(obj) { // At this point there are two references (x and obj) in memory, // but these both point to the same object. // changing the object will change the underlying object that // x and obj both hold a reference to. obj.val = obj.val * 10; } var x = { val: 10 }; changeObject(x); // x === { val: 100 }

Un ejemplo más:

function changeObject(obj) { // Again there are two references (x and obj) in memory, // these both point to the same object. // now we create a completely new object and assign it. // obj''s reference now points to the new object. // x''s reference doesn''t change. obj = { val: 100 }; } var x = { val: 10 }; changeObject(x); // x === { val: 10}


Siempre se pasa por valor, pero para los objetos, el valor de la variable es una referencia. Debido a esto, cuando pasa un objeto y cambia sus miembros , esos cambios persisten fuera de la función. Esto hace que parezca pasar por referencia. Pero si realmente cambia el valor de la variable de objeto, verá que el cambio no persiste, lo que demuestra que realmente se pasa por valor.

Ejemplo:

function changeObject(x) { x = {member:"bar"}; alert("in changeObject: " + x.member); } function changeMember(x) { x.member = "bar"; alert("in changeMember: " + x.member); } var x = {member:"foo"}; alert("before changeObject: " + x.member); changeObject(x); alert("after changeObject: " + x.member); /* change did not persist */ alert("before changeMember: " + x.member); changeMember(x); alert("after changeMember: " + x.member); /* change persists */

Salida:

before changeObject: foo in changeObject: bar after changeObject: foo before changeMember: foo in changeMember: bar after changeMember: bar


En un lenguaje de bajo nivel, si desea pasar una variable por referencia, debe usar una sintaxis específica en la creación de la función:

int myAge = 14; increaseAgeByRef(myAge); function increaseAgeByRef(int &age) { *age = *age + 1; }

El &agees una referencia a myAge, pero si desea que el valor que tiene para convertir la referencia, utilizando *age.

Javascript es un lenguaje de alto nivel que hace esta conversión por ti. Entonces, aunque los objetos se pasan por referencia, el lenguaje convierte el parámetro de referencia al valor. No es necesario utilizar &, en la definición de la función, para pasarla por referencia, tampoco *, en el cuerpo de la función, para convertir la referencia al valor, JS lo hace por usted.

Es por eso que cuando intenta cambiar un objeto dentro de una función, al reemplazar su valor (es decir age = {value:5}), el cambio no persiste, pero si cambia sus propiedades (es decir age.value = 5), sí lo hace.

Aprende más


Los valores simples dentro de las funciones no cambiarán esos valores fuera de la función (se pasan por valor), mientras que los valores complejos (se pasan por referencia).

function willNotChange(x) { x = 1; } var x = 1000; willNotChange(x); document.write(''After function call, x = '' + x + ''<br>''); //still 1000 function willChange(y) { y.num = 2; } var y = {num: 2000}; willChange(y); document.write(''After function call y.num = '' + y.num + ''<br>''); //now 2, not 2000


Mi manera simple de entender esto ...

  • Al llamar a una función, está pasando el contenido (referencia o valor) de las variables de argumento, no las variables en sí.

    var var1 = 13; var var2 = { prop: 2 }; //13 and var2''s content (reference) are being passed here foo(var1, var2);

  • Dentro de la función, las variables de parámetros, inVar1y inVar2, reciben los contenidos que se están pasando.

    function foo(inVar1, inVar2){ //changing contents of inVar1 and inVar2 won''t affect variables outside inVar1 = 20; inVar2 = { prop: 7 }; }

  • Desde que inVar2recibió la referencia de { prop: 2 }, puede cambiar el valor de la propiedad del objeto.

    function foo(inVar1, inVar2){ inVar2.prop = 7; }


Yo diría que es paso por copia -

Considere que los argumentos y los objetos variables son objetos creados durante el contexto de ejecución creado al comienzo de la invocación de la función, y su valor / referencia real pasado a la función simplemente se almacena en estos argumentos + objetos variables.

En pocas palabras, para los tipos primitivos, los valores se copian al comienzo de la llamada a la función, para el tipo de objeto, la referencia se copia.


¡¡Semántica!! Establecer definiciones concretas necesariamente hará que algunas respuestas y comentarios sean incompatibles, ya que no describen lo mismo incluso cuando se usan las mismas palabras y frases, pero es fundamental superar la confusión (especialmente para los nuevos programadores).

En primer lugar, hay múltiples niveles de abstracción que no todos parecen captar. Los programadores más nuevos que han aprendido en los lenguajes de 4ta o 5ta generación pueden tener dificultades para comprender conceptos familiares para ensambladores o programadores en C que no van en fases por punteros a punteros a indicadores. Paso por referencia no significa simplemente la capacidad de cambiar un objeto referenciado usando una variable de parámetro de función.

Variable : concepto combinado de un símbolo que hace referencia a un valor en una ubicación particular en la memoria. Este término es generalmente demasiado cargado para ser usado solo al discutir los detalles.

Símbolo : cadena de texto utilizada para referirse a la variable (es decir, el nombre de la variable).

Valor : Bits particulares almacenados en la memoria y referenciados usando el símbolo de la variable.

Ubicación de memoria : donde se almacena el valor de una variable. (La ubicación en sí está representada por un número independiente del valor almacenado en la ubicación).

Parámetro de función : Variable declarada en una definición de función, utilizada para hacer referencia a las variables pasadas a la función.

Argumento de la función : Variable fuera de la función que la persona que llama pasa a la función.

Variable de objeto : Variable cuyo valor subyacente básico no es el "objeto" en sí, sino que su valor es un puntero (valor de ubicación de memoria) a otra ubicación en la memoria donde se almacenan los datos reales del objeto. En la mayoría de los lenguajes de la generación superior, el aspecto "puntero" se oculta de manera efectiva mediante la falta de referencia automática en diversos contextos.

Variable primitiva : variable cuyo valor es el valor real. Incluso este concepto puede complicarse con el autoajuste y los contextos tipo objeto de varios idiomas, pero las ideas generales son que el valor de la variable es el valor real representado por el símbolo de la variable en lugar de un puntero a otra ubicación de memoria.

Los argumentos de función y los parámetros no son lo mismo. Además, el valor de una variable no es el objeto de la variable (como ya lo señalaron varias personas, pero aparentemente se ignoró). Estas distinciones son críticas para una correcta comprensión.

Pasar por valor o Llamar por compartir (para objetos): El valor del argumento de la función está COPIADO a otra ubicación de memoria a la que se hace referencia mediante el símbolo de parámetro de la función (independientemente de si está en la pila o en el montón). En otras palabras, el parámetro de función recibió una copia del valor del argumento pasado ... Y (crítico) el valor del argumento NUNCA ESTÁ ACTUALIZADO / ALTERADO / CAMBIADO por la función de llamada. Recuerde, el valor de una variable de objeto NO es el objeto en sí, sino que es el puntero al objeto, por lo que al pasar una variable de objeto por valor se copia el puntero a la variable de parámetro de función. El valor del parámetro de la función apunta exactamente al mismo objeto en la memoria. Los datos del objeto en sí pueden modificarse directamente a través del parámetro de función, PERO el valor del argumento de la función NUNCA SE ACTUALIZA, por lo que continuará apuntando al mismoObjeto completo e incluso después de la llamada a la función (incluso si se modificaron los datos de su objeto o si el parámetro de la función tiene asignado un objeto completamente diferente). Es incorrecto concluir que el argumento de la función se pasó por referencia solo porque el objeto al que se hace referencia es actualizable a través de la variable de parámetro de la función.

Llamada / paso por referencia : el valor del argumento de la función se puede / se actualizará directamente con el parámetro de la función correspondiente. Si ayuda, el parámetro de función se convierte en un "alias" efectivo para el argumento: efectivamente se refieren al mismo valor en la misma ubicación de memoria. Si un argumento de función es una variable de objeto, la capacidad de cambiar los datos del objeto no es diferente del caso de paso por valor, ya que el parámetro de función seguirá apuntando al mismo objeto que el argumento. Pero en el caso de la variable de objeto, si el parámetro de la función se establece en un objeto completamente diferente, entonces el argumento también apuntará al objeto diferente, esto no sucede en el caso de pasar por valor.

JavaScript no pasa por referencia. Si lees atentamente, te darás cuenta de que todas las opiniones contrarias entienden mal lo que se entiende por paso por valor y concluyen falsamente que la capacidad de actualizar los datos de un objeto mediante el parámetro de función es sinónimo de "paso por valor".

Copia / copia del objeto: se crea un nuevo objeto y se copian los datos del objeto original. Esto puede ser una copia profunda o una copia superficial, pero el punto es que se crea un nuevo objeto. La creación de una copia de un objeto es un concepto separado del paso por valor. Algunos idiomas distinguen entre objetos de clase y estructuras (o similares), y pueden tener diferentes comportamientos para pasar variables de los diferentes tipos. Pero JavaScript no hace nada como esto automáticamente cuando pasa variables de objeto. Pero la ausencia de clonación automática de objetos no se traduce en una referencia paso a paso.


En algunos casos, esto puede ser útil para alterar anArg:

function alterMyArg(func) { // process some data // ... func(data); } alertMyArg(function(d) {anArg = d;});


Esta es una explicación un poco más para Pasar por valor y Pasar por referencia (Javascript). En este concepto, están hablando de pasar la variable por referencia y pasar la variable por referencia.

Pase por valor (tipo primitivo)

var a = 3; var b = a; console.log(a); // a = 3 console.log(b); // b = 3 a=4; console.log(a); // a = 4 console.log(b); // b = 3

  • se aplica a todos los tipos primitivos en JS (cadena, número, booleano, indefinido, nulo).
  • a se asigna una memoria (por ejemplo, 0x001) yb crea una copia del valor en la memoria (por ejemplo, 0x002).
  • Por lo tanto, cambiar el valor de una variable no afecta a la otra, ya que ambos residen en dos ubicaciones diferentes.

Pasar por referencia (objetos)

var c = { "name" : "john" }; var d = c; console.log(c); // { "name" : "john" } console.log(d); // { "name" : "john" } c.name = "doe"; console.log(c); // { "name" : "doe" } console.log(d); // { "name" : "doe" }

  • El motor JS asigna el objeto a la variable c, apunta a algo de memoria, por ejemplo (0x012)
  • cuando d = c, en este paso d apunta a la misma ubicación (0x012).
  • cambiando el valor de cualquier valor de cambios tanto para la variable.
  • las funciones son objetos

Caso especial, Pasar por referencia (objetos)

c = {"name" : "jane"}; console.log(c); // { "name" : "jane" } console.log(d); // { "name" : "doe" }

  • El operador igual (=) configura un nuevo espacio de memoria o dirección

Hay un poco de debate sobre el uso del término "paso por referencia" en JS here , pero para responder a su pregunta:

Un objeto se pasa automáticamente por referencia, sin la necesidad de indicarlo específicamente

(Del artículo mencionado anteriormente.)


He encontrado que el método extendido de la biblioteca Underscore.js es muy útil cuando quiero pasar un objeto como parámetro que puede modificarse o reemplazarse por completo.

function replaceOrModify(aObj) { if (modify) { aObj.setNewValue(''foo''); } else { var newObj = new MyObject(); // _.extend(destination, *sources) _.extend(newObj, aObj); } }


He leído estas respuestas varias veces, pero REALMENTE no lo entendí hasta que me enteré de la definición técnica de "Llamar compartiendo", como la llama Barbara Liskov.

La semántica de la llamada al compartir difiere de la llamada por referencia en que las asignaciones a los argumentos de la función dentro de la función no son visibles para la persona que llama (a diferencia de la semántica de referencia) [cita requerida], por lo que, por ejemplo, si se pasó una variable, no es posible para simular una asignación en esa variable en el alcance de la persona que llama. Sin embargo, como la función tiene acceso al mismo objeto que la persona que llama (no se realiza ninguna copia), las mutaciones en esos objetos, si los objetos son mutables, dentro de la función son visibles para la persona que llama, lo que puede parecer que difiere de la llamada por el valor semántica. Las mutaciones de un objeto mutable dentro de la función son visibles para la persona que llama porque el objeto no se copia ni se clona, ​​sino que se comparte.

Es decir, las referencias de los parámetros se pueden modificar si vas y accedes al valor del parámetro en sí. Por otro lado, la asignación a un parámetro desaparecerá después de la evaluación, y la persona que llama a la función no podrá acceder a ella.


La explicación más breve que encontré fue en la guía de estilo AirBNB :

  • Primitivas : cuando accede a un tipo primitivo, trabaja directamente en su valor

    • cuerda
    • número
    • booleano
    • nulo
    • indefinido

P.ej:

var foo = 1, bar = foo; bar = 9; console.log(foo, bar); // => 1, 9

  • Complejo : cuando accede a un tipo complejo, trabaja en una referencia a su valor

    • objeto
    • formación
    • función

P.ej:

var foo = [1, 2], bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // => 9, 9

En efecto, los tipos primitivos se pasan por valor y los tipos complejos se pasan por referencia.


Las primitivas se pasan por valor y los objetos se pasan por referencia. Esto es bastante diferente de otros idiomas como C, VB o Delphi. No puedo decir exactamente cómo manejan los objetos y primitivas, pero sé de VB y Delphi que se puede (y debería) especificar.

php hace algo similar desde la versión 5: todos los objetos se pasan por referencia, pero todas las primitivas se pueden pasar por referencia, si son precedidas por un signo (&). De lo contrario, las primitivas se pasan por valor.

Entonces, en javascript, si paso un objeto X a una función a través de un parámetro, seguirá siendo X. Si está cambiando datos dentro de la función (o cualquier otro objeto, pero eso no es importante), ese nuevo valor también está disponible fuera del función.


Para los abogados de lenguaje de programación, he revisado las siguientes secciones de ECMAScript 5.1 (que es más fácil de leer que la edición más reciente) y llego a asking en la lista de correo de ECMAScript.

TL; DR : Todo se pasa por valor, pero las propiedades de los Objetos son referencias, y la definición de Objeto carece asombrosamente del estándar.

Construcción de listas de argumentos

La sección 11.2.4 "Listas de argumentos" dice lo siguiente al generar una lista de argumentos que consta de solo 1 argumento:

La ArgumentList de producción: AssignmentExpression se evalúa de la siguiente manera:

  1. Sea ref el resultado de evaluar AssignmentExpression.
  2. Que arg sea GetValue (ref).
  3. Devuelve una lista cuyo único artículo es arg.

La sección también enumera los casos donde la lista de argumentos tiene 0 o> 1 argumentos.

Así, todo se pasa por referencia.

Acceso a las propiedades del objeto.

Sección 11.2.1 "Accesores de propiedades"

La producción MemberExpression: MemberExpression [Expresión] se evalúa de la siguiente manera:

  1. Deje que baseReference sea el resultado de evaluar MemberExpression.
  2. Deje que baseValue sea GetValue (baseReference).
  3. Deje que propertyNameReference sea el resultado de evaluar Expresión.
  4. Deje que propertyNameValue sea GetValue (propertyNameReference).
  5. Llame a CheckObjectCoercible (baseValue).
  6. Deje que propertyNameString sea ToString (propertyNameValue).
  7. Si la producción sintáctica que se está evaluando está contenida en un código de modo estricto, permita que estrictamente sea verdadero, de lo contrario, sea estrictamente falso.
  8. Devuelve un valor de tipo Reference cuyo valor base es baseValue y cuyo nombre de referencia es propertyNameString, y cuyo indicador de modo estricto es estricto.

Por lo tanto, las propiedades de los objetos están siempre disponibles como referencia.

En referencia

Se describe en la sección 8.7 "El tipo de especificación de referencia", que las referencias no son tipos reales en el idioma, solo se usan para describir el comportamiento de los operadores de eliminación, tipo y asignación.

Definición de "Objeto"

Se define en la edición 5.1 que "Un objeto es una colección de propiedades". Por lo tanto, podemos inferir, que el valor del objeto es la colección, pero en cuanto a cuál es el valor de la colección está mal definido en la especificación y requiere un poco de effort para comprenderlo.


Una forma fácil de determinar si algo es "pasar por referencia" es si puede escribir una función de "intercambio". Por ejemplo, en C, puedes hacer:

void swap(int *i, int *j) { int t; t = *i; *i = *j; *j = t; }

Si no puede hacer el equivalente de eso en Javascript, no es "pasar por referencia".