2016-05-27 13 views
9

Lubię myśleć, że rozumiem JavaScript, ale znalazłem dzisiaj coś nieoczekiwanego i miałem nadzieję, że ktoś może mi wyjaśnić, dlaczego tak się dzieje.Używanie słowa kluczowego "this" w obiekcie JavaScript

wziąć to kod

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," ")) 

Wyjście nie jest to, czego się spodziewałem. Wywołanie animalData.getCow() wyników w "cow" tak, jak można się spodziewać. Ale to, co dostaje powrót przez sekundę console.log, co wprowadza mnie w błąd.

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

Innymi słowy, przedmiotem własności animalId usuwa całkowicie z obiektów określonych. Spodziewałem się tego

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

I mogę zrozumieć Może to

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

Ale dlaczego nieruchomość animalId zostaną usunięte całkowicie?

Czy ktoś może wyjaśnić, co dzieje się pod powierzchnią, aby spowodować takie zachowanie? Zgaduję, że słowo kluczowe this nie działa, ponieważ właściwości są niezdefiniowane, gdy jest wywoływana, ale dlaczego całkowicie usuwa tę właściwość?

NB: Nie szukam obejścia, to dość proste - po prostu interesuje mnie, dlaczego tak się dzieje.

JSFiddle here

+0

Na losowej notatce. Dlaczego używasz string string JSON do logowania obiektu? Po prostu użyj konsoli console.log/console.dir, aby w łatwy sposób zbadać obiekt. – evolutionxbox

+0

@evolutionxbox Innym sposobem na sprawdzenie tego jest to, że po prostu używa on 'console.log', aby zobaczyć efekt wiązania tego obiektu, a nie to, że on je podpisuje. –

+0

@evolutionxbox Jednym z powodów może być to, że jeśli zarejestrujesz obiekt bezpośrednio, po rozwinięciu obiektu w konsoli otrzymasz ** bieżące ** wartości, a nie wartości tego obiektu, gdy był on zalogowany. Dzieje się tak dlatego, że po prostu rejestrując obiekt, przeglądarka zapisuje jedynie odniesienie do tego obiektu, a nie do głębokiej kopii bieżącego obiektu. – Cristy

Odpowiedz

6

W momencie przedmiot jest zainicjowany, this odnosi się do zewnętrznej kontekście, który nie będzie miał cow i sheep właściwości. Jak myślałeś, spowoduje to, że animalId jest undefined.

JSON.stringify does certain things z undefined właściwości, mianowicie:

If undefined, funkcję, czy symbol napotkano podczas konwersji jest albo pominięte (gdy znajduje się w obiekcie) lub cenzurowane do null (gdy zostanie znaleziony w tablicy).

Dlatego ich nie widzisz.

+0

Brilliant. Dzięki za jasne wyjaśnienie. Nie wiedziałem o JSON.stringify. Może to utrudnić debugowanie. Będę używał czegoś takiego jak JSON.stringify (animalData.animalList, function (k, v) {return (v === undefined)? Null: v;}); ); – Toby

4

Przede wszystkim masz rację twój ostatni przykład, to co próbujesz stringify:

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

A ponieważ te wartości są niezdefiniowane JSON.stringify prostu pomija je. Dlaczego powyższe wartości są niezdefiniowane, ponieważ słowo kluczowe w this.cow odnosi się do bieżącego zakresu, który w rzeczywistości jest obiektem window, ponieważ nie znajduje się w żadnej innej funkcji.

Dlaczego warto pomijać klucze o wartościach undefined?Ponieważ istnieją lub nie, jeśli spróbujesz uzyskać dostęp do object.key, otrzymasz poprawną wartość: undefined

+0

Jeśli nie stworzysz obiektu animalData z 'new', czy" this "nie zawsze będzie odnosić się do' okna'? – evolutionxbox

+0

@evolutionxbox To zależy. Funkcja 'getCow' odwoła się do poprawnego' this', ponieważ jest wywoływana jako funkcja na obiekcie. –

+0

@evolutionxbox Jego 'animalData' nie jest klasą, która może być utworzona za pomocą nowego, ale prostego' Obiektu'. Nie można utworzyć instancji obiektu 'animalData' (nie ma zdefiniowanego konstruktora). – Cristy

Powiązane problemy