2010-05-07 12 views
107

Können sagen, ich habe folgendes javascript:Wie kann ein Javascript-Objekt auf Werte an sich verweisen?

var obj = { 
key1 : "it ", 
key2 : key1 + " works!" 
}; 
alert(obj.key2); 

Diese Fehler mit "key1 ist nicht definiert". Ich habe versucht

this.key1 
this[key1] 
obj.key1 
obj[key1] 
this["key1"] 
obj["key1"] 

und sie scheinen nie definiert zu sein.

Wie kann key2 auf den Wert von key1 verweisen?

+0

Sehr alte Versionen von Firefox (habe ich versucht, Firefox 4 und es gibt eine Warnung aus, sondern akzeptiert Es ermöglicht Ihnen, # N = und # N # zu verwenden, um auf vorhandene Objekte in demselben Ausdruck zu verweisen, aber dies funktioniert nicht für Grundelemente; Sie müssen diese nur duplizieren. – Neil

+1

Eigentlich gibt es eine käsige Problemumgehung, Sie können das Primitiv boxen und dann auf den Boxed-Wert mit der scharfen Variable verweisen: 'var obj = {key1: # 1 = (neuer String (" it ")), key2: # 1 # + "funktioniert!" }; alert (obj.key2) ' – Neil

+0

key2 ist innerhalb des Objekts definiert, während das Objekt definiert wird. Es gibt also noch keinen key1 wenn key2 definiert wird. Erst nach der Zuweisung existiert key1. Sie verweisen auf etwas, das noch nicht existiert. –

Antwort

122

Vielleicht können Sie darüber nachdenken, das Attribut zu einer Funktion zu entfernen. Ich meine, so etwas wie diese:

var obj = { 
key1 : "it ", 
key2 : function() {return this.key1 + " works!";} 
}; 

alert(obj.key2()); 
+4

es funktioniert nur, wenn Sie eine flache 'obj' haben, wie die in Ihrem Beispiel. Es wird nicht funktionieren, wenn Sie verschachtelte Schlüssel haben. – Green

+1

@Green True, aber Sie könnten es immer sofort nach der Objekterstellung einer gebundenen Funktion zuweisen. 'var obj = {...}; obj.nested.func = function() {...} .bind (obj); ' – Thor84no

+4

In ES6 können Sie' key2: function() {...} 'durch' get key2() {...} ersetzen 'und dann brauchst du keine Klammern beim Aufruf:' alert (obj.key2); ' – JoeRocc

5

Dies ist nicht JSON. JSON wurde entworfen, um einfach zu sein; willkürliche Ausdrücke zuzulassen, ist nicht einfach.

In voller JavaScript, ich glaube nicht, dass Sie dies direkt tun können. Sie können nicht auf this verweisen, bis das Objekt obj vollständig aufgebaut ist. Du brauchst also einen Workaround, dass jemand mit mehr JavaScript-Fu als ich bereitstellen wird.

34

Sie können nicht auf eine Eigenschaft eines Objekts verweisen, bevor Sie dieses Objekt initialisiert haben. Verwenden Sie eine externe Variable.

var key1 = "it"; 
var obj = { 
    key1 : key1, 
    key2 : key1 + " works!" 
}; 

Auch dies ist kein "JSON-Objekt"; Es ist ein Javascript-Objekt. JSON ist eine Methode zum Darstellen eines Objekts mit einer Zeichenfolge (die zufällig gültiger JavaScript-Code ist).

14

Das ist kein JSON Objekt, das ist ein Javascript-Objekt, das über Objekt-Literal-Notation erzeugt wird. (JSON ist eine textuelle Notation für den Datenaustausch (more). Wenn Sie mit JavaScript-Quellcode zu tun hat, und es nicht mit einem String, du bist nicht mit JSON zu tun.)

Es gibt keine Möglichkeit, innerhalb der Objektinitialisierer verweist auf einen anderen Schlüssel des Objekts, das initialisiert wird, da es keine Möglichkeit gibt, einen Verweis auf das Objekt zu erhalten, das erstellt wird, bis der Initialisierer beendet ist. (Es gibt kein Schlüsselwort ähnlich wie this oder etwas für diese Situation.)

19

Da die Anweisung definiert obj nicht beendet hat, key1 noch nicht existiert. Betrachten Sie diese Lösung:

var obj = { key1: "it" }; 
obj.key2 = obj.key1 + ' ' + 'works!'; 
// obj.key2 is now 'it works!' 
+0

nette Lösung, macht Sinn, dass das Objekt seine Ausführungsphase noch nicht beendet hat, also wäre das Aufrufen eines Schlüssels nicht definiert. Objekte sind Funktionen, so dass Schlüssel innerhalb des Speichers nicht definiert sind, bis die Ausführungsphase beendet ist. – Pixelomo

38

Dies kann durch Verwendung Konstruktorfunktion statt wörtliche

var o = new function() { 
    this.foo = "it"; 
    this.bar = this.foo + " works" 
} 

alert(o.bar) 
7

Sie auch die obj verweisen kann erreicht werden, wenn Sie innerhalb der Funktion statt this sind.

var obj = { 
    key1: "it", 
    key2: function(){return obj.key1 + " works!"} 
}; 
alert(obj.key2()); 
+0

Ich denke, diese Antwort ist der 'besten Antwort' überlegen. obj.key1 ist immer 'it', während this.key1 ein anderer Wert sein kann, abhängig davon, wo die Funktion obj.key2 aufgerufen wird. z.B. setTimeout (obj.key2, 100); Dies bezieht sich auf das Fensterobjekt. –

15

Eine Alternative wäre die Verwendung einer Getter/Setter-Methode.

Zum Beispiel, wenn Sie nur über das Lesen der berechnete Wert Pflege:

var book = {} 

Object.defineProperties(book,{ 
    key1: { value: "it", enumerable: true }, 
    key2: { 
     enumerable: true, 
     get: function(){ 
      return this.key1 + " works!"; 
     } 
    } 
}); 

console.log(book.key2); //prints "it works!" 

Der obige Code, aber lassen Sie nicht einen anderen Wert für key2 definieren.

So werden die Dinge ein bisschen komplizierter, wenn Sie auch den Wert von key2 neu definieren möchten. Es wird immer ein berechneter Wert sein. Das ist wahrscheinlich das, was Sie wollen.

Wenn Sie jedoch den Wert von key2 neu definieren möchten, benötigen Sie einen Platz, um seinen Wert unabhängig von der Berechnung zwischenzuspeichern.

Etwas wie folgt aus:

var book = { _key2: " works!" } 

Object.defineProperties(book,{ 
    key1: { value: "it", enumerable: true}, 
    _key2: { enumerable: false}, 
    key2: { 
     enumerable: true, 
     get: function(){ 
      return this.key1 + this._key2; 
     }, 
     set: function(newValue){ 
      this._key2 = newValue; 
     } 
    } 
}); 

console.log(book.key2); //it works! 

book.key2 = " doesn't work!"; 
console.log(book.key2); //it doesn't work! 

for(var key in book){ 
    //prints both key1 and key2, but not _key2 
    console.log(key + ":" + book[key]); 
} 

Eine weitere interessante Alternative ist, ein selbst Initialisierung Objekt zu verwenden:

var obj = ({ 
    x: "it", 
    init: function(){ 
    this.y = this.x + " works!"; 
    return this; 
    } 
}).init(); 

console.log(obj.y); //it works! 
+0

Ich mag den selbst initialisierenden Objekt - Weg. Danke – suther

Verwandte Themen