389 Stimmen

Übergabe von Variablen per Referenz in JavaScript

Wie übergebe ich Variablen per Referenz in JavaScript?

Ich habe drei Variablen, mit denen ich mehrere Operationen durchführen möchte, also möchte ich sie in eine for-Schleife setzen und die Operationen mit jeder einzelnen durchführen.

Pseudocode:

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

Wie lässt sich dies am besten bewerkstelligen?

532voto

Pointy Punkte 387467

In JavaScript gibt es keine "Übergabe per Referenz". Sie können ein Objekt übergeben (d.h. Sie können einen Verweis auf ein Objekt per Wert übergeben) und dann den Inhalt des Objekts durch eine Funktion ändern lassen:

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

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

alterObject(myObj);

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

Sie können über die Eigenschaften eines Arrays mit einem numerischen Index iterieren und jede Zelle des Arrays ändern, wenn Sie möchten.

var arr = [1, 2, 3];

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

Es ist wichtig zu wissen, dass der Begriff "Pass-by-Reference" ein sehr spezifischer Begriff ist. Er bedeutet nicht einfach, dass es möglich ist, einen Verweis auf ein veränderbares Objekt zu übergeben. Stattdessen bedeutet es, dass es möglich ist, eine einfache Variable so zu übergeben, dass eine Funktion diesen Wert in der aufrufen Kontext. So:

 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"

In einer Sprache wie C++ ist das möglich, weil diese Sprache fait haben (sozusagen) Pass-by-Reference.

bearbeiten - das ist vor kurzem (März 2015) auf Reddit wieder hochgegangen, und zwar wegen eines Blogbeitrags, der meinem unten erwähnten ähnlich ist, allerdings in diesem Fall über Java. Beim Lesen des Hin und Her in den Reddit-Kommentaren fiel mir auf, dass ein großer Teil der Verwirrung auf die unglückliche Kollision mit dem Wort "Referenz" zurückzuführen ist. Die Terminologie "pass by reference" und "pass by value" geht auf das Konzept der "Objekte" in Programmiersprachen zurück. In Wirklichkeit geht es gar nicht um Objekte, sondern um Funktionsparameter und insbesondere darum, wie Funktionsparameter mit der aufrufenden Umgebung "verbunden" sind (oder nicht). Beachten Sie insbesondere, dass in einer echten Pass-by-Reference-Sprache - einer Sprache, die fait Objekte einbeziehen - man hätte immer noch die Möglichkeit, das Objekt zu ändern Inhalt und es würde ziemlich genau so aussehen, wie es in JavaScript der Fall ist. Allerdings würde man auch in der Lage sein, den Objektverweis in der aufrufenden Umgebung zu ändern, und das ist das Wichtigste, was Sie kann nicht in JavaScript zu tun. Eine Pass-by-Reference-Sprache würde nicht die Referenz selbst übergeben, sondern eine Verweis auf die Referenz .

bearbeiten - hier ist ein Blogbeitrag zum Thema. (Beachten Sie den Kommentar zu diesem Beitrag, der erklärt, dass C++ nicht wirklich Pass-by-Reference hat. Das ist richtig. Was C++ jedoch hat, ist die Möglichkeit, Verweise auf einfache Variablen zu erstellen, entweder explizit am Punkt des Funktionsaufrufs, um einen Zeiger zu erstellen, oder implizit beim Aufruf von Funktionen, deren Argumenttypsignatur dies erfordert. Das sind die wichtigsten Dinge, die JavaScript nicht unterstützt).

181voto

Mukund Kumar Punkte 17476
  1. Variablen vom primitiven Typ wie Strings und Zahlen werden immer als Wert übergeben.
  2. Arrays und Objekte werden je nach diesen Bedingungen als Referenz oder als Wert übergeben:
  • wenn Sie den Wert eines Objekts oder Arrays setzen, ist es Pass by Value.

     object1 = { prop: "car" };
     array1 = [1,2,3];
  • wenn Sie einen Eigenschaftswert eines Objekts oder Arrays ändern, dann ist es Pass by Reference.

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

Code

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

30voto

user2410595 Punkte 349

Umgehung der Übergabe von Variablen wie bei einer Referenz:

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

inc('a');

alert(a); // 2

Und ja, man kann es tatsächlich tun, ohne auf eine globale Variable zuzugreifen:

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

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

    return init;
})();

inc();

19voto

Eduardo Cuomo Punkte 15791

Einfaches Objekt

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"

Benutzerdefiniertes Objekt

Objekt 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);

6voto

Pavlo Mur Punkte 350

Eine weitere Möglichkeit, beliebige (lokale, primitive) Variablen per Referenz zu übergeben, besteht darin, die Variable "on the fly" mit einer Closure zu umhüllen, indem eval . Dies funktioniert auch mit "use strict". (Hinweis: Beachten Sie, dass eval ist nicht freundlich zu JavaScript-Optimierern, und auch fehlende Anführungszeichen um Variablennamen können zu unvorhersehbaren Ergebnissen führen)

"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);
})()

Live-Probe: https://jsfiddle.net/t3k4403w/

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X