2016-05-27 9 views
9

Ich mag es zu denken, dass ich JavaScript verstehe, aber ich fand etwas unerwartetes heute und ich hoffte, dass jemand mir erklären könnte, warum es passiert.Verwenden von 'dieses' Schlüsselwort in JavaScript-Objekt

Nehmen Sie diesen Code

var animalData = { 
        cow:"cow", 
        sheep:"sheep", 
        getCow:function() 
        { 
        return this.cow; 
        }, 
        animalList:[ 
          { 
          animalId:this.cow, 
          label:"This is a cow" 
          }, 
          { 
          animalId:this.sheep, 
          label:"This is a sheep" 
          } 
         ] 
      }; 

console.log(animalData.getCow()); 
console.log(JSON.stringify(animalData.animalList,null," ")) 

Der Ausgang ist nicht das, was ich erwartet hatte. Rufen Sie animalData.getCow() Ergebnisse in "cow" auf, wie Sie es erwarten würden. Aber es ist, was durch die zweite console.log Rückkehr erhält, die mich verwirrt.

[ 
{ 
    "label": "This is a cow" 
}, 
{ 
    "label": "This is a sheep" 
} 
] 

Mit anderen Worten, entfernt das Objekt die animalId Eigenschaft vollständig aus den definierten Objekten. Ich hatte erwartet, dieses

[ 
{ 
    "animalId":"cow", 
    "label": "This is a cow" 
}, 
{ 
    "animalId":"sheep", 
    "label": "This is a sheep" 
} 
] 

Und ich könnte vielleicht dieses

[ 
{ 
    "animalId":undefined, 
    "label": "This is a cow" 
}, 
{ 
    "animalId":undefined, 
    "label": "This is a sheep" 
} 
] 

verstehen Aber warum die animalId Eigenschaft erhalten vollständig entfernt?

Kann jemand erklären, was unter der Oberfläche passiert, um dieses Verhalten zu verursachen? Ich vermute, dass das Schlüsselwort this nicht funktioniert, weil die Eigenschaften nicht definiert sind, wenn es aufgerufen wird, aber warum wird die Eigenschaft vollständig entfernt?

NB: Ich suche keine Workaround, das ist einfach genug zu tun - nur daran interessiert, warum es passiert.

JSFiddle here

+0

Auf eine zufällige Notiz. Warum verwenden Sie JSON stringify, um ein Objekt zu protokollieren? Verwenden Sie einfach console.log/console.dir, damit Sie das Objekt leicht untersuchen können. – evolutionxbox

+0

@evolutionxbox Eine andere Möglichkeit, es zu betrachten, ist, dass er nur 'console.log' benutzt, um den Effekt des Stringings dieses Objekts zu sehen, nicht, dass er es stringt, um es zu loggen. –

+0

@evolutionxbox Ein Grund wäre, dass, wenn Sie das Objekt direkt protokollieren, wenn Sie das Objekt in der Konsole erweitern, Sie die ** aktuellen ** Werte erhalten, nicht die Werte dieses Objekts, wenn es protokolliert wurde. Dies liegt daran, dass der Browser bei der einfachen Protokollierung des Objekts nur eine Referenz auf dieses Objekt speichert und keine tiefe Kopie des aktuellen Objekts. – Cristy

Antwort

6

An dem Punkt, das Objekt initialisiert wird, bezieht this auf den äußeren Rahmen, der nicht cowsheep und Eigenschaften haben. Wie Sie dachten, wird dies dazu führen, dass animalId s undefined ist.

JSON.stringify does certain things mit undefined Eigenschaften, nämlich:

Wenn undefined, eine Funktion oder ein Symbol wird während der Umwandlung aufgetreten ist es entweder weggelassen oder zensiert null (wenn es in einem Objekt gefunden wird) (wenn es in einem Array gefunden wird).

Deshalb sehen Sie sie nicht.

+0

Brilliant. Danke für eine klare Erklärung. Das wusste ich nicht über JSON.stringify. Es kann das Debugging erschweren. Ich werde etwas wie JSON.stringify verwenden (animalData.animalList, Funktion (k, v) {return (v === undefiniert)? Null: v;}); ); – Toby

4

Zu allererst Sie richtig Ihrem letzten Beispiel sind, das ist, was Sie zu stringify versuchen:

[ 
{ 
    "animalId":undefined, 
    "label": "This is a cow" 
}, 
{ 
    "animalId":undefined, 
    "label": "This is a sheep" 
} 
] 

Und weil diese Werte sind nicht definiert JSON.stringify sich einfach weglässt. Warum die obigen Werte nicht definiert sind, liegt daran, dass sich das Schlüsselwort this in this.cow auf den aktuellen Bereich bezieht, der eigentlich das Objekt window ist, da es sich in keiner anderen Funktion befindet.

Warum ist es sinnvoll, Tasten mit undefined Werten wegzulassen?Denn ob sie existieren oder nicht, wenn Sie versuchen, auf object.key zuzugreifen erhalten Sie den richtigen Wert: undefined

+0

Wenn Sie das animalData-Objekt nicht mit 'new' instanziieren, bezieht sich' this' nicht immer auf das 'window'? – evolutionxbox

+0

@evolutionxbox Es kommt darauf an. Die 'getCow'-Funktion referenziert das korrekte' this', weil es als eine Funktion für das Objekt aufgerufen wird. –

+0

@evolutionxbox Seine 'animalData' ist keine Klasse, die mit neuen, sondern einem einfachen' Objekt' instanziiert werden kann. Sie können ein TierData-Objekt nicht instanziieren (es ist kein Konstruktor definiert). – Cristy

Verwandte Themen