Hvordan sender jeg variabler som referanse i JavaScript? Jeg har 3 variabler som jeg vil utføre flere operasjoner på, så jeg vil sette dem i en for-løkke og utføre operasjonene på hver enkelt.
pseudokode:
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 vars
Hva er den beste måten å gjøre dette på?
Det finnes ingen "pass by reference"-funksjon i JavaScript. Du kan sende et objekt (det vil si at du kan sende en referanse til et objekt) og deretter få en funksjon til å endre objektets innhold:
function alterObject(obj) {
obj.foo = "goodbye";
}
var myObj = { foo: "hello world" };
alterObject(myObj);
alert(myObj.foo); // "goodbye" instead of "hello world"
Du kan iterere over egenskapene til en matrise med en numerisk indeks og endre hver celle i matrisen, hvis du vil.
var arr = [1, 2, 3];
for (var i = 0; i < arr.length; i++) {
arr[i] = arr[i] + 1;
}
Det er viktig å merke seg at " pass-by-referanse " er et veldig spesifikt begrep. Det betyr ikke bare at det er mulig å sende en referanse til et modifiserbart objekt. I stedet betyr det at det er mulig å sende en enkel variabel på en slik måte at en funksjon kan endre den verdien i **kallingskonteksten. Så:
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"
I et språk som C++ er det mulig å gjøre det fordi det språket har (slags) pass-by-referanse.
rediger — dette nylig (mars 2015) blåste opp på Reddit igjen over et blogginnlegg som ligner på mitt nevnt nedenfor, men i dette tilfellet om Java. Det slo meg mens jeg leste frem og tilbake i Reddit-kommentarene at en stor del av forvirringen stammer fra den uheldige kollisjonen som involverer ordet "referanse". Terminologien "pass by reference" og "pass by value" er eldre enn konseptet med å ha "objekter" å jobbe med i programmeringsspråk. Det handler egentlig ikke om objekter i det hele tatt; det handler om funksjonsparametere, og spesielt hvordan funksjonsparametere er "koblet" (eller ikke) til miljøet som kaller. Legg spesielt merke til at i en ekte pass-by-referanse språk — en som gjør involverer objekter — man ville fortsatt ha muligheten til å endre objektet innhold, og det ville se ganske mye akkurat som det gjør i JavaScript. Imidlertid ville man også være i stand til å endre objektreferansen i anropsmiljøet, og det er det viktigste du ikke kan gjøre i JavaScript. Et pass-by-referanse språk vil ikke sende selve referansen, men en referanse til referansen.
edit — her er et blogginnlegg om emnet. (Legg merke til kommentaren til det innlegget som forklarer at C++ egentlig ikke har pass-by-referanse. Det er sant. Hva C++ har, er imidlertid muligheten til å opprette referanser til vanlige variabler, enten eksplisitt på det punktet av funksjon påkalling for å opprette en peker, eller implisitt når du kaller funksjoner hvis argument type signatur krever at det skal gjøres. Dette er de viktigste tingene JavaScript ikke støtter).
Omgåelse for å sende variabel som ved referanse:
var a = 1;
inc = function(variableName) {
window[variableName] += 1;
};
inc('a');
alert(a); // 2
EDIT
yup, faktisk kan du gjøre det uten tilgang global
inc = (function () {
var variableName = 0;
var init = function () {
variableName += 1;
alert(variableName);
}
return init;
})();
inc();
var ref = { value: 1 };
function Foo(x) {
x.value++;
}
Foo(ref);
Foo(ref);
alert(ref.value); // Alert: 3
rvar
function rvar (name, value, context) {
if (this instanceof rvar) {
this.value = value;
Object.defineProperty(this, 'name', { value: name });
Object.defineProperty(this, 'hasValue', { get: function () { return this.value !== undefined; } });
if ((value !== undefined) && (value !== null))
this.constructor = value.constructor;
this.toString = function () { return this.value + ''; };
} else {
if (!rvar.refs)
rvar.refs = {};
if (!context)
context = window;
// Private
rvar.refs[name] = new rvar(name, value);
// Public
Object.defineProperty(context, name, {
get: function () { return rvar.refs[name]; },
set: function (v) { rvar.refs[name].value = v; },
configurable: true
});
return context[name];
}
}
rvar('test_ref');
test_ref = 5; // test_ref.value = 5
Or:
rvar('test_ref', 5); // test_ref.value = 5
rvar('test_ref_number');
test_ref_number = 5;
function Fn1 (v) { v.value = 100; }
console.log("rvar('test_ref_number');");
console.log("test_ref_number = 5;");
console.log("function Fn1 (v) { v.value = 100; }");
console.log('test_ref_number.value === 5', test_ref_number.value === 5);
console.log(" ");
Fn1(test_ref_number);
console.log("Fn1(test_ref_number);");
console.log('test_ref_number.value === 100', test_ref_number.value === 100);
console.log(" ");
test_ref_number++;
console.log("test_ref_number++;");
console.log('test_ref_number.value === 101', test_ref_number.value === 101);
console.log(" ");
test_ref_number = test_ref_number - 10;
console.log("test_ref_number = test_ref_number - 10;");
console.log('test_ref_number.value === 91', test_ref_number.value === 91);
console.log(" ");
console.log("---------");
console.log(" ");
rvar('test_ref_str', 'a');
console.log("rvar('test_ref_str', 'a');");
console.log('test_ref_str.value === "a"', test_ref_str.value === 'a');
console.log(" ");
test_ref_str += 'bc';
console.log("test_ref_str += 'bc';");
console.log('test_ref_str.value === "abc"', test_ref_str.value === 'abc');
rvar('test_ref_number');
test_ref_number = 5;
function Fn1 (v) { v.value = 100; }
test_ref_number.value === 5 true
Fn1(test_ref_number);
test_ref_number.value === 100 true
test_ref_number++;
test_ref_number.value === 101 true
test_ref_number = test_ref_number - 10;
test_ref_number.value === 91 true
---------
rvar('test_ref_str', 'a');
test_ref_str.value === "a" true
test_ref_str += 'bc';
test_ref_str.value === "abc" true