Pasar variables por referencia en JavaScript

15 minutos de lectura

Pasar variables por referencia en JavaScript
BFTrick

¿Cómo paso variables por referencia en JavaScript?

Tengo tres variables con las que quiero realizar varias operaciones, así que quiero ponerlas en un bucle for y realizar las operaciones en cada una.

Pseudocódigo:

myArray = new Array(var1, var2, var3);
for (var x = 0; x < myArray.length; x++){
    // Do stuff to the array
    makePretty(myArray[x]);
}
// Now do stuff to the updated variables

¿Cuál es la mejor manera de hacer esto?

  • Está hablando de ‘pasar por referencia’, pero no tiene llamadas de función en su ejemplo, por lo que no hay ningún paso en su ejemplo. Por favor, aclare lo que está tratando de hacer.

    – jfriend00

    12/10/2011 a las 18:44

  • Perdón por la confusion. No necesitaba específicamente escribir una función, por lo que ‘pasar por referencia’ fue una mala elección de palabras. Solo quiero poder realizar algunas operaciones con variables sin escribir makePretty(var1); makePretty(var2); makePretty(var3); ...

    – BFTrick

    17 de octubre de 2011 a las 15:28


  • basado en tu comentario: arr = [var1, var2, var3]; for (var i = 0, len = arr.length; i < len; i++) { arr[i] = makePretty(arr[i]); } — solo necesita almacenar el valor devuelto por makePretty de nuevo en la ranura de la matriz.

    – dylnmc

    17 mayo 2017 a las 17:29


  • Para aquellos que vienen de Google mientras buscan “pass-by-reference” o “pass-by-value” en Javascript, un buen artículo es este de Medium: medio.com/@TK_CodeBear/…

    –Erenor Paz

    30 de noviembre de 2020 a las 16:09


1646970854 622 Pasar variables por referencia en JavaScript
puntiagudo

No hay “pasar por referencia” disponible en JavaScript. Puede pasar un objeto (es decir, puede pasar por valor una referencia a un objeto) y luego hacer que una función modifique el contenido del objeto:

function alterObject(obj) {
  obj.foo = "goodbye";
}

var myObj = { foo: "hello world" };

alterObject(myObj);

alert(myObj.foo); // "goodbye" instead of "hello world"

Puede iterar sobre las propiedades de una matriz con un índice numérico y modificar cada celda de la matriz, si lo desea.

var arr = [1, 2, 3];

for (var i = 0; i < arr.length; i++) { 
    arr[i] = arr[i] + 1; 
}

Es importante tener en cuenta que “pasar por referencia” es un término muy específico. No significa simplemente que es posible pasar una referencia a un objeto modificable. En cambio, significa que es posible pasar una variable simple de tal manera que permita que una función modifique ese valor en el vocación contexto. Entonces:

 function swap(a, b) {
   var tmp = a;
   a = b;
   b = tmp; //assign tmp to b
 }

 var x = 1, y = 2;
 swap(x, y);

 alert("x is " + x + ", y is " + y); // "x is 1, y is 2"

En un lenguaje como C++, es posible hacer eso porque ese lenguaje lo hace (más o menos) tienen paso por referencia.

editar — esto recientemente (marzo de 2015) explotó en Reddit nuevamente por una publicación de blog similar a la mía que se menciona a continuación, aunque en este caso sobre Java. Mientras leía los comentarios de Reddit, se me ocurrió que gran parte de la confusión proviene de la desafortunada colisión que involucra la palabra “referencia”. La terminología “pasar por referencia” y “pasar por valor” es anterior al concepto de tener “objetos” con los que trabajar en los lenguajes de programación. Realmente no se trata de objetos en absoluto; se trata de los parámetros de la función, y específicamente de cómo los parámetros de la función están “conectados” (o no) al entorno de llamada. En particular, tenga en cuenta que en un verdadero lenguaje de paso por referencia, uno que lo hace involucrar objetos: uno todavía tendría la capacidad de modificar el objeto contenido, y se vería casi exactamente como lo hace en JavaScript. Sin embargo, uno además ser capaz de modificar la referencia del objeto en el entorno de llamada, y esa es la clave que usted hipocresía hacer en JavaScript. Un lenguaje de paso por referencia no pasaría la referencia en sí misma, sino un referencia a la referencia.

editarAquí hay una publicación de blog sobre el tema. (Tenga en cuenta el comentario de esa publicación que explica que C ++ realmente no tiene paso por referencia. Eso es cierto. Sin embargo, lo que C ++ tiene es la capacidad de crear referencias a variables simples, ya sea explícitamente en el punto de función invocación para crear un puntero, o implícitamente al llamar a funciones cuya firma de tipo de argumento exige que se haga eso. Esas son las cosas clave que JavaScript no admite).

  • Puede pasar una referencia a un objeto o una matriz que le permite cambiar el objeto o la matriz original, que creo que es lo que realmente pregunta el OP.

    – jfriend00

    12/10/2011 a las 18:35

  • Bueno, el OP usó la terminología, pero el código real no parece implicar ningún “paso” en absoluto 🙂 No estoy realmente seguro de lo que está tratando de hacer.

    – Puntiagudo

    12/10/2011 a las 18:47

  • Pasar una referencia por valor no es lo mismo que pasar por referenciaaunque puede parecerlo en algunos escenarios como este.

    – Travis Webb

    2 de diciembre de 2013 a las 16:13


  • Tu bloguero se equivoca con C++, que lo hace pass-by-reference, y su publicación no tiene sentido. Es irrelevante que no pueda cambiar el valor de una referencia después de la inicialización; eso no tiene nada que ver con ‘pasar por referencia’. Su declaración de que ‘La semántica “pasar por referencia” se puede rastrear a través de C#’ debería haber hecho sonar una alarma.

    – EML

    29/10/2014 a las 19:14

  • @Pointy Esta es una respuesta horrible. Si necesitara ayuda, lo último que querría es que alguien me enseñara semántica. “Pasar por referencia” simplemente significa “la función, hasta cierto punto, puede cambiar el valor de la variable que se pasó como argumento”. (en el contexto de la pregunta) Realmente no es tan complicado como parece.

    – rey sin corona

    20 de junio de 2017 a las 2:57

Pasar variables por referencia en JavaScript
Mukund Kumar

  1. Las variables de tipo primitivo como cadenas y números siempre se pasan por valor.
  2. Las matrices y los objetos se pasan por referencia o por valor según estas condiciones:
  • si está configurando el valor de un objeto o matriz, es Pasar por valor.

     object1 = { prop: "car" };
     array1 = [1,2,3];
    
  • si está cambiando el valor de una propiedad de un objeto o matriz, entonces es Pasar por referencia.

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

Código

function passVar(obj1, obj2, num) {
    obj1.prop = "laptop"; // will CHANGE original
    obj2 = { prop: "computer" }; //will NOT affect original
    num = num + 1; // will NOT affect original
}

var object1 = {
    prop: "car"
};
var object2 = {
    prop: "bike"
};
var number1 = 10;

passVar(object1, object2, number1);
console.log(object1); // output: Object { prop: "laptop" }
console.log(object2); // output: Object { prop: "bike" }
console.log(number1); // ouput: 10

  • Ese no es el significado de “pasar por referencia”. El término realmente no tiene nada que ver con objetos, sino con la relación entre los parámetros en una función llamada y las variables en el entorno de llamada.

    – Puntiagudo

    23 de marzo de 2015 a las 19:52

  • Todo siempre se pasa por valor. Con no primitivas, el valor que se pasa es una referencia. Asignar a una referencia cambia esa referencia, naturalmente, ya que es un valor, y por lo tanto no puede cambiar el otro objeto al que se hizo referencia originalmente. La mutación del objeto al que apunta una referencia actúa exactamente como cabría esperar, al mutar el objeto al que apunta. Ambos escenarios son perfectamente coherentes y ninguno altera mágicamente el funcionamiento de JavaScript retrocediendo en el tiempo y cambiando la forma en que se pasaron a la función.

    – Mateo Lee

    21 de marzo de 2017 a las 18:51


  • Esta respuesta aclaró la anterior, que, aunque tiene más votos (287 en el momento de escribir este artículo y también es la aceptada) no era lo suficientemente clara en cuanto a cómo pasarla por referencia en JS. En breve, el código en esta respuesta funcionó, la respuesta que reunió más votos no funcionó.

    – Papanicolaou

    25 de octubre de 2017 a las 7:09

  • Esas respuestas realmente llegan al punto de lo que se puede hacer y lo que no se puede hacer para responder a la necesidad de OP. En lugar de debatir sobre qué significa “pasar por referencia”, creo que todos podemos estar de acuerdo en que la terminología es terrible y esperamos que se acuñe una mejor en el futuro cercano. Si bien la respuesta de @Pointy me permitió comprender más los conceptos, esa me ayudó a hacer el trabajo.

    – Rafiki

    27 de enero a las 8:49

Pasar variables por referencia en JavaScript
usuario2410595

Solución alternativa para pasar variables como por referencia:

var a = 1;
inc = function(variableName) {
  window[variableName] += 1;
};

inc('a');

alert(a); // 2

Y sí, en realidad puedes hacerlo sin acceder a una variable global:

inc = (function () {
    var variableName = 0;

    var init = function () {
        variableName += 1;
        alert(variableName);
    }

    return init;
})();

inc();

  • @Phil, es bueno tener cuidado con los valores globales/de ventana, pero en algún momento todo lo que estamos haciendo en el navegador es un elemento secundario o descendiente del objeto de ventana. En nodejs, todo es descendiente de GLOBAL. En los lenguajes de objetos compilados, ese es un objeto principal implícito, si no explícito, porque hacerlo de otra manera hace que la administración del montón sea más complicada (¿y para qué?).

    – dkloke

    28 de marzo de 2015 a las 7:45

  • @dkloke: Sí, eventualmente se debe tocar el objeto de la ventana, como jQuery usa window.$/window.jQuery y otros métodos están debajo de esto. Estaba hablando de la contaminación del espacio de nombres global donde se agregan muchas variables en lugar de tenerlas bajo un espacio de nombres unificador.

    – Phil

    29 de marzo de 2015 a las 21:26

  • No encuentro buenas palabras para expresar lo malo que es ese enfoque ;(

    – SOReader

    24 de marzo de 2016 a las 15:16

  • Me encanta la última solución (versión editada) incluso que no pasa variable por referencia. Esa es una ventaja porque puede acceder a las variables directamente.

    – Juan Boe

    7 de septiembre de 2016 a las 7:01

1646970855 819 Pasar variables por referencia en JavaScript
eduardo cuomo

objeto sencillo

function foo(x) {
  // Function with other context
  // Modify `x` property, increasing the value
  x.value++;
}

// Initialize `ref` as object
var ref = {
  // The `value` is inside `ref` variable object
  // The initial value is `1`
  value: 1
};

// Call function with object value
foo(ref);
// Call function with object value again
foo(ref);

console.log(ref.value); // Prints "3"

Objeto personalizado

Objeto rvar

/**
 * Aux function to create by-references variables
 */
function rvar(name, value, context) {
  // If `this` is a `rvar` instance
  if (this instanceof rvar) {
    // Inside `rvar` context...

    // Internal object value
    this.value = value;

    // Object `name` property
    Object.defineProperty(this, 'name', { value: name });

    // Object `hasValue` property
    Object.defineProperty(this, 'hasValue', {
      get: function () {
        // If the internal object value is not `undefined`
        return this.value !== undefined;
      }
    });

    // Copy value constructor for type-check
    if ((value !== undefined) && (value !== null)) {
      this.constructor = value.constructor;
    }

    // To String method
    this.toString = function () {
      // Convert the internal value to string
      return this.value + '';
    };
  } else {
    // Outside `rvar` context...

    // Initialice `rvar` object
    if (!rvar.refs) {
      rvar.refs = {};
    }

    // Initialize context if it is not defined
    if (!context) {
      context = this;
    }

    // Store variable
    rvar.refs[name] = new rvar(name, value, context);

    // Define variable at context
    Object.defineProperty(context, name, {
      // Getter
      get: function () { return rvar.refs[name]; },
      // Setter
      set: function (v) { rvar.refs[name].value = v; },
      // Can be overrided?
      configurable: true
    });

    // Return object reference
    return context[name];
  }
}

// Variable Declaration

// Declare `test_ref` variable
rvar('test_ref_1');

// Assign value `5`
test_ref_1 = 5;
// Or
test_ref_1.value = 5;

// Or declare and initialize with `5`:
rvar('test_ref_2', 5);

// ------------------------------
// Test Code

// Test Function
function Fn1(v) { v.value = 100; }

// Test
function test(fn) { console.log(fn.toString()); console.info(fn()); }

// Declare
rvar('test_ref_number');

// First assign
test_ref_number = 5;
test(() => test_ref_number.value === 5);

// Call function with reference
Fn1(test_ref_number);
test(() => test_ref_number.value === 100);

// Increase value
test_ref_number++;
test(() => test_ref_number.value === 101);

// Update value
test_ref_number = test_ref_number - 10;
test(() => test_ref_number.value === 91);

1646970856 5 Pasar variables por referencia en JavaScript
pavlo mur

Otro enfoque más para pasar cualquier variable (local, primitiva) por referencia es envolver la variable con el cierre “sobre la marcha” por eval. Esto también funciona con “uso estricto”. (Nota: tenga en cuenta que eval no es amigable con los optimizadores de JavaScript, y también la falta de comillas alrededor del nombre de la variable puede causar resultados impredecibles)

"use strict"

// Return text that will reference variable by name (by capturing that variable to closure)
function byRef(varName){
    return "({get value(){return "+varName+";}, set value(v){"+varName+"=v;}})";
}

// Demo

// Assign argument by reference
function modifyArgument(argRef, multiplier){
    argRef.value = argRef.value * multiplier;
}

(function(){
    var x = 10;

    alert("x before: " + x);
    modifyArgument(eval(byRef("x")), 42);
    alert("x after: " + x);
})()

Muestra en vivo: https://jsfiddle.net/t3k4403w/

  • Buena idea, pero decidí no hacerlo porque para las variables de solo salida que pasan una función de flecha x=>value=x es en realidad más corto, mientras que los parámetros de entrada-salida bidireccionales no se requieren tan a menudo. Ver mi respuesta a una pregunta duplicada para otra evalenfoque basado en, donde pasa nombres de variables y evalúa el resultado de toda la función.

    – Hormiga_222

    14/03/2021 a las 15:20


1646970856 395 Pasar variables por referencia en JavaScript
nicho

De hecho, hay una bonita solución:

function updateArray(context, targetName, callback) {
    context[targetName] = context[targetName].map(callback);
}

var myArray = ['a', 'b', 'c'];
updateArray(this, 'myArray', item => {return '_' + item});

console.log(myArray); //(3) ["_a", "_b", "_c"]

  • Buena idea, pero decidí no hacerlo porque para las variables de solo salida que pasan una función de flecha x=>value=x es en realidad más corto, mientras que los parámetros de entrada-salida bidireccionales no se requieren tan a menudo. Ver mi respuesta a una pregunta duplicada para otra evalenfoque basado en, donde pasa nombres de variables y evalúa el resultado de toda la función.

    – Hormiga_222

    14/03/2021 a las 15:20


1646970857 509 Pasar variables por referencia en JavaScript
bart holanda

Personalmente, no me gusta la funcionalidad de “pasar por referencia” que ofrecen varios lenguajes de programación. Tal vez sea porque recién estoy descubriendo los conceptos de la programación funcional, pero siempre se me pone la piel de gallina cuando veo funciones que causan efectos secundarios (como manipular parámetros pasados ​​por referencia). Personalmente, acepto firmemente el principio de “responsabilidad única”.

En mi humilde opinión, una función debe devolver solo un resultado/valor usando la palabra clave de retorno. En lugar de modificar un parámetro/argumento, simplemente devolvería el valor del parámetro/argumento modificado y dejaría las reasignaciones deseadas hasta el código de llamada.

Pero a veces (esperemos que muy rara vez), es necesario devolver dos o más valores de resultado de la misma función. En ese caso, optaría por incluir todos esos valores resultantes en una sola estructura u objeto. Nuevamente, el procesamiento de cualquier reasignación debe depender del código de llamada.

Ejemplo:

Supongamos que el paso de parámetros sería compatible con el uso de una palabra clave especial como ‘ref’ en la lista de argumentos. Mi código podría ser algo como esto:

//The Function
function doSomething(ref value) {
    value = "Bar";
}

//The Calling Code
var value = "Foo";
doSomething(value);
console.log(value); //Bar

En cambio, en realidad preferiría hacer algo como esto:

//The Function
function doSomething(value) {
    value = "Bar";
    return value;
}

//The Calling Code:
var value = "Foo";
value = doSomething(value); //Reassignment
console.log(value); //Bar

Cuando necesitaría escribir una función que devuelva múltiples valores, tampoco usaría parámetros pasados ​​por referencia. Así que evitaría un código como este:

//The Function
function doSomething(ref value) {
    value = "Bar";

    //Do other work
    var otherValue = "Something else";

    return otherValue;
}

//The Calling Code
var value = "Foo";
var otherValue = doSomething(value);
console.log(value); //Bar
console.log(otherValue); //Something else

En cambio, preferiría devolver ambos valores nuevos dentro de un objeto, así:

//The Function
function doSomething(value) {
    value = "Bar";

    //Do more work
    var otherValue = "Something else";

    return {
        value: value,
        otherValue: otherValue
    };
}

//The Calling Code:
var value = "Foo";
var result = doSomething(value);
value = result.value; //Reassignment
console.log(value); //Bar
console.log(result.otherValue);

Estos ejemplos de código están bastante simplificados, pero demuestran aproximadamente cómo manejaría personalmente esas cosas. Me ayuda a mantener varias responsabilidades en el lugar correcto.

Codificación feliz. 🙂

  • Asignar y reasignar cosas (sin ningún tipo de verificación también) es lo que me pone la piel de gallina. En cuanto a la responsabilidad, espero que doSomething() haga eso, no haga eso más haga un objeto más y asigne mis variables a las propiedades. Digamos que tengo una matriz que debe buscarse. Me gustaría que los elementos coincidentes se colocaran en una segunda matriz y quiero saber cuántos se encontraron. Una solución estándar sería llamar a una función como esta: ‘var foundArray; if ((findStuff(inArray, &foundArray)) > 1) { // proceso foundArray}’. En ninguna parte de ese escenario es deseable o necesario un objeto nuevo y desconocido.

    – Elise van Looij

    13 de agosto de 2019 a las 11:16

  • @ElisevanLooij En su caso de ejemplo, preferiría tener findStuff simplemente devuelva la matriz resultante. Usted también tiene que declarar un foundArray variable, por lo que le asignaría directamente la matriz resultante: var foundArray = findStuff(inArray); if (foundArray.length > 0) { /* process foundArray */ }. Esto 1) haría que el código de llamada fuera más legible/comprensible, y 2) simplificaría considerablemente la funcionalidad interna (y por lo tanto también la capacidad de prueba) del findStuff método, lo que lo hace mucho más flexible en diferentes (re)uso-casos/escenarios.

    – Bart Höfland

    13 de agosto de 2019 a las 13:46

  • @ElisevanLooij Sin embargo, estoy de acuerdo en que las reasignaciones (como en mi respuesta) son de hecho un “olor a código” y también me gustaría evitarlas tanto como sea posible. Pensaré en editar (o incluso reformular) mi respuesta de tal manera que refleje mejor mi opinión real sobre el tema. Gracias por tu reacción. 🙂

    – Bart Höfland

    13 de agosto de 2019 a las 13:46

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad