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?

5voto

Bart Hofland Punkte 3420

Ich persönlich mag die "pass by reference"-Funktionalität nicht, die von verschiedenen Programmiersprachen angeboten wird. Vielleicht liegt es daran, dass ich die Konzepte der funktionalen Programmierung gerade erst entdecke, aber ich bekomme immer eine Gänsehaut, wenn ich Funktionen sehe, die Seiteneffekte verursachen (wie die Manipulation von Parametern, die per Referenz übergeben werden). Ich persönlich bin ein großer Anhänger des Prinzips der "einzigen Verantwortung".

IMHO sollte eine Funktion nur ein Ergebnis/Wert mit dem Schlüsselwort return zurückgeben. Anstatt einen Parameter/ein Argument zu ändern, würde ich nur den geänderten Parameter-/Argumentenwert zurückgeben und alle gewünschten Neuzuweisungen dem aufrufenden Code überlassen.

Aber manchmal (hoffentlich sehr selten) ist es notwendig, zwei oder mehr Ergebniswerte aus derselben Funktion zurückzugeben. In diesem Fall würde ich mich dafür entscheiden, alle diese Ergebniswerte in einer einzigen Struktur oder einem einzigen Objekt zusammenzufassen. Auch hier sollte die Verarbeitung von Neuzuweisungen dem aufrufenden Code überlassen werden.

Beispiel:

Angenommen, die Übergabe von Parametern wird durch die Verwendung eines speziellen Schlüsselworts wie "ref" in der Argumentliste unterstützt. Mein Code könnte etwa so aussehen:

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

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

Stattdessen würde ich es vorziehen, so etwas zu tun:

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

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

Wenn ich eine Funktion schreiben müsste, die mehrere Werte zurückgibt, würde ich auch keine Parameter verwenden, die als Referenz übergeben werden. Ich würde also Code wie diesen vermeiden:

//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

Stattdessen würde ich es vorziehen, beide neuen Werte innerhalb eines Objekts zurückzugeben, etwa so:

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

Diese Code-Beispiele sind ziemlich vereinfacht, aber sie zeigen grob, wie ich persönlich mit solchen Dingen umgehen würde. Es hilft mir, verschiedene Verantwortlichkeiten an der richtigen Stelle zu behalten.

Viel Spaß beim Codieren :)

4voto

Adam Wise Punkte 1685

Ich habe mit der Syntax herumgespielt, um diese Art von Dingen zu tun, aber es erfordert einige Helfer, die ein wenig ungewöhnlich sind. Es fängt damit an, dass ich überhaupt keine 'var' verwende, sondern eine einfache 'DECLARE'-Hilfe, die eine lokale Variable erstellt und einen Bereich für sie über einen anonymen Rückruf definiert. Indem wir kontrollieren, wie Variablen deklariert werden, können wir sie in Objekte verpacken, so dass sie im Wesentlichen immer per Referenz übergeben werden können. Dies ähnelt einer der obigen Antworten von Eduardo Cuomo, aber die folgende Lösung erfordert nicht die Verwendung von Strings als Variablenbezeichner. Hier ist ein minimaler Code, um das Konzept zu zeigen.

function Wrapper(val){
    this.VAL = val;
}
Wrapper.prototype.toString = function(){
    return this.VAL.toString();
}

function DECLARE(val, callback){
    var valWrapped = new Wrapper(val);    
    callback(valWrapped);
}

function INC(ref){
    if(ref && ref.hasOwnProperty('VAL')){
        ref.VAL++; 
    }
    else{
        ref++;//or maybe throw here instead?
    }

    return ref;
}

DECLARE(5, function(five){ //consider this line the same as 'let five = 5'
console.log("five is now " + five);
INC(five); // increment
console.log("five is incremented to " + five);
});

4voto

Mateus Araújo Punkte 61

Es gibt sogar eine hübsche Lösung:

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"]

2voto

Eigentlich ist es ganz einfach. Das Problem ist, zu verstehen, dass einmal übergeben klassische Argumente, Sie in einem anderen scoped sind, Nur-Lese-Zone.

Die Lösung besteht darin, die Argumente mithilfe des objektorientierten Designs von JavaScript zu übergeben. Das ist dasselbe wie die Übergabe der Argumente in einer globalen/eingespeicherten Variablen, aber besser...

function action(){
  /* Process this.arg, modification allowed */
}

action.arg = [["empty-array"], "some string", 0x100, "last argument"];
action();

Sie können auch Versprechen um in den Genuss der bekannten Kette zu kommen: Hier ist die ganze Sache, mit versprechungsähnliche Struktur

function action(){
  /* Process this.arg, modification allowed */
  this.arg = ["a", "b"];
}

action.setArg = function(){this.arg = arguments; return this;}

action.setArg(["empty-array"], "some string", 0x100, "last argument")()

Oder besser noch...

action.setArg(["empty-array"],"some string",0x100,"last argument").call()

2voto

JavaScript kann Array-Elemente innerhalb einer Funktion ändern (es wird als Referenz auf das Objekt/Array übergeben).

function makeAllPretty(items) {
   for (var x = 0; x < myArray.length; x++){
      // Do stuff to the array
      items[x] = makePretty(items[x]);
   }
}

myArray = new Array(var1, var2, var3);
makeAllPretty(myArray);

Hier ein weiteres Beispiel:

function inc(items) {
  for (let i=0; i < items.length; i++) {
    items[i]++;
  }
}

let values = [1,2,3];
inc(values);
console.log(values);
// Prints [2,3,4]

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