Javascript Referenzen
J o
- javascript
Moin,
ich hab eine Frage zu Referenzen. Dazu ein kleines Beispiel:
var data = {a: 1, b: 2, c:3};
var f = function(){
this.a = data.a; //Keine Referenz?
this.d = data; //Referenz
this.geta = function(){
return this.a;
}
this.getd = function(){
return this.d;
}
}
var foo = new f();
Object.assign(data, {a: 5, d:6}); // ändert f.d
// ändert f.a NICHT
console.log(foo.geta());
console.log(foo.getd());
Erstens, warum ist this.a = data.a;
anscheinend keine Referenz? Beziehungsweise was ist mein Denkfehler?
Und Zweitens, wie kann man eine Referenz auf eine Eigenschaft eines Objektes erzeugen.
(Möchte das ungern mit "setter-Funktionen" machen, da sich das durch sehr viele Instanzen zeiht).
Gruß
Jo
Tach!
Erstens, warum ist
this.a = data.a;
anscheinend keine Referenz? Beziehungsweise was ist mein Denkfehler?
Bei primitiven Typen wird der Wert übergeben, da sie einfach kopiert werden können. Objekte können beliebig verschachtelt sein, auch rekursiv, da wird der Einfachheit halber eine Referenz weitergegeben.
Und Zweitens, wie kann man eine Referenz auf eine Eigenschaft eines Objektes erzeugen.
Meines Wissens nach gar nicht, wenn es sich dabei um primitive Typen handelt. Du könntest den Wert in ein Objekt betten, à la new Number(42)
, aber das gibt keinen Vorteil. Der Wert dieses Objekts ist nicht änderbar. Wenn du der Eigenschaft deines Objekts ein neues solches Wrapper-Objekt zuweist, bricht das genauso die Referenz wie wenn du vorher den Wert kopiert hättest.
data.a = 42
a = data.a; // Kopie
data.a = 23;
// a ist immer noch 42
data.a = new Number(42)
a = data.a; // Referenz
data.a = new Number(23);
// a ist immer noch Number(42)
dedlfix.
Hey,
Erstens, warum ist
this.a = data.a;
anscheinend keine Referenz? Beziehungsweise was ist mein Denkfehler?Bei primitiven Typen wird der Wert übergeben, da sie einfach kopiert werden können. Objekte können beliebig verschachtelt sein, auch rekursiv, da wird der Einfachheit halber eine Referenz weitergegeben.
Auch Eigenschaften die wiederum Objekt sind werden nicht referenziert.
Und Zweitens, wie kann man eine Referenz auf eine Eigenschaft eines Objektes erzeugen.
[...] Der Wert dieses Objekts ist nicht änderbar. Wenn du der Eigenschaft deines Objekts ein neues solches Wrapper-Objekt zuweist, bricht das genauso die Referenz wie wenn du vorher den Wert kopiert hättest.
Dann werde ich wohl um set a()
nicht herum kommen. Vielen Dank!
Gruß
Jo
Tach!
Auch Eigenschaften die wiederum Objekt sind werden nicht referenziert.
Object.assign(data, {a: { x: 5, y: 9 }, d:6});
Wenn du data.a mit einem neuen Objekt überschreibst, zeigen die angelegten Referenzen weiterhin auf das alte Objekt. Wenn du stattdessen data.a.x = 5
nimmst, wirst du den Unterschied sehen. a bleibt erhalten und dessen Eingenschaft 5 bekommt einen neuen Wert zugewiesen.
dedlfix.
Tach!
Auch Eigenschaften die wiederum Objekt sind werden nicht referenziert.
Object.assign(data, {a: { x: 5, y: 9 }, d:6});
Wenn du data.a mit einem neuen Objekt überschreibst, zeigen die angelegten Referenzen weiterhin auf das alte Objekt. Wenn du stattdessen
data.a.x = 5
nimmst, wirst du den Unterschied sehen. a bleibt erhalten und dessen Eingenschaft 5 bekommt einen neuen Wert zugewiesen.
Ja, aber das wäre zu komplex, bzw wären zu viele Zeilen.
Gruß
Jo
Hallo Jo,
die aus PHP oder C++ bekannten Referenzen auf beliebige Variablen gibt es in JavaScript nicht.
Aber vielleicht kannst Du Dich mit einem selbstgebaunten Funktor[1] behelfen?
let SomeClass = function() {
this.a = 17;
};
let makeRefFunctor = function (obj, property) {
return function(newValue) {
return (arguments.length > 0) ?
(obj[property] = newValue) :
obj[property];
}
}
let obj = new SomeClass();
let refA = makeRefFunctor(obj, "a");
console.log(refA());
refA(32);
console.log(refA());
SomeClass ist eine beliebige Klasse mit der Eigenschaft a.
makeReference erzeugt eine anonyme Funktion, die einen optionalen Parameter newValue bekommt. Da dieses Funktionsobjekt den Scope dieses makeReference-Aufrufs als Closure mitnimmt und später auch nutzt, wird es zum Funktor, der für ein bestimmtes Objekt eine bestimmte Eigenschaft lesen und schreiben kann.
Der Funktor muss eine richtige Funktion sein, keine Pfeilfunktion, damit arguments
definiert ist. Damit kann man abfragen, wieviele Parameter übergeben wurden und so steuern, ob der Funktor als getter oder setter agieren soll.
Alternativ kann man auch eine Klasse PropertyRef bauen. Die macht nichts anderes als der Funktor, speichert aber Objekt und Propertyname explizit und steuert den Zugriff über getter und setter einer Value-Eigenschaft.
class PropertyRef {
constructor(obj, property) {
this.object = obj;
this.property = property;
}
get value() { return this.object[this.property]; }
set value(newValue) { this.object[this.property] = newValue; }
}
let obj = new SomeClass();
let pRefA = new PropertyRef(obj, "a");
console.log(pRefA.value);
pRefA.value = 47;
console.log(pRefA.value);
Rolf
Definition Funktor in C++: Ein Objekt, das den Operator ()
überlädt. Letztlich ist das in JavaScript für jede Funktion der Fall; ein Funktor hat aber im Gegensatz zu einer normalen Funktion die Möglichkeit, sich Informationen zu merken. Das verwenden wir hier. ↩︎
Hey,
Man könnte es sich auch einfach einfach machen:
var data = {a: { x: 1, y: 2 }, b: 2, c:3}; var f = function(d){ this.getd = function(){ return d; } } var foo = new f(data);
Gruß
Jo