if (klucz w obiekcie) lub if (obiekt.hasOwnProperty (klucz)


173

Czy poniższe dwie instrukcje dają takie same wyniki? Czy jest jakiś powód, by preferować jedną od drugiej?

 if (key in object)

 if (object.hasOwnProperty(key))

Odpowiedzi:


181

Uważaj - nie dadzą tego samego rezultatu.

inzwróci również, truejeśli keyzostanie znaleziony gdzieś w łańcuchu prototypów , podczas gdy Object.hasOwnProperty(jak nazwa już nam mówi), zwróci tylko truewtedy, gdy keyjest dostępny bezpośrednio w tym obiekcie („posiada” właściwość).


3
co dokładnie masz na myśli in will also return true if key gets found somewhere in the prototype chain. czy możesz napisać przykład? dzięki.
Lorraine Bernard

44
@Lor: ({foo:"bar"}).hasOwnProperty("toString")vs"toString" in ({foo:"bar"})
I Hate Lazy

68

Spróbuję wyjaśnić na innym przykładzie. Powiedzmy, że mamy następujący obiekt z dwiema właściwościami:

function TestObj(){
    this.name = 'Dragon';
}
TestObj.prototype.gender = 'male';

Stwórzmy instancję TestObj:

var o = new TestObj();

Przyjrzyjmy się instancji obiektu:

console.log(o.hasOwnProperty('name')); // true
console.log('name' in o); // true

console.log(o.hasOwnProperty('gender')); // false
console.log('gender' in o); // true

Wniosek:

  • operator in zawsze zwraca prawdę, jeśli właściwość jest dostępna dla obiektu, bezpośrednio lub z prototypu

  • hasOwnProperty () zwraca wartość true tylko wtedy, gdy właściwość istnieje w instancji, ale nie w jej prototypie

Gdybyśmy chcieli sprawdzić, czy w prototypie istnieje jakaś właściwość, logicznie powiedzielibyśmy:

console.log(('name' in o) && !o.hasOwnProperty('name')); //false
console.log(('gender' in o) && !o.hasOwnProperty('gender')); //true - it's in prototype

Wreszcie:

A więc, jeśli chodzi o stwierdzenie, że te dwa warunki ...

if (key in object)
if (object.hasOwnProperty(key))

... dają ten sam wynik, odpowiedź jest oczywista, to zależy.


28

insprawdzi również dziedziczone właściwości, co nie ma miejsca w przypadku hasOwnProperty.


25

Podsumowując, hasOwnProperty()nie wygląda w prototypie, podczas gdy inwygląda w prototypie.

Zaczerpnięte z O'Reilly High Performance Javascript :

Możesz określić, czy obiekt ma element członkowski instancji o podanej nazwie, używając metody hasOwnProperty () i przekazując nazwę elementu członkowskiego. Aby określić, czy obiekt ma dostęp do właściwości o podanej nazwie, możesz użyć operatora in. Na przykład:

var book = {
    title: "High Performance JavaScript",
    publisher: "Yahoo! Press" 
};

alert(book.hasOwnProperty("title"));  //true
alert(book.hasOwnProperty("toString"));  //false
alert("title" in book); //true 
alert("toString" in book); //true

W tym kodzie hasOwnProperty () zwraca prawdę, gdy przekazano „tytuł”, ponieważ tytuł jest instancją obiektu; metoda zwraca false, gdy przekazano „toString”, ponieważ nie istnieje w instancji. Gdy każda nazwa właściwości jest używana z operatorem in, wynik jest prawdziwy za każdym razem, ponieważ przeszukuje instancję i prototyp.


5

Masz naprawdę świetne odpowiedzi. Chcę tylko zaoferować coś, co zaoszczędzi ci potrzeby sprawdzania "hasOwnProperty" podczas iteracji obiektu.

Tworząc obiekt zazwyczaj ludzie będą go tworzyć w ten sposób:

const someMap = {}
// equivalent to: Object.create(Object.prototype)
// someMap.constructor will yield -> function Object() { [native code] }

Teraz, jeśli chcesz iterować przez "someMap", będziesz musiał to zrobić w ten sposób:

const key
for(key in someMap ){
 if (someMap.hasOwnProperty(key)) { 
   // Do something
 }
}

Robimy to, aby uniknąć iteracji po odziedziczonych właściwościach.

Jeśli zamierzasz stworzyć prosty obiekt, który będzie używany tylko jako „mapa” (tj. Pary klucz-wartość), możesz to zrobić w następujący sposób:

const newMap = Object.create(null);
// Now, newMap won't have prototype at all.
// newMap.constructor will yield -> undefined

Więc teraz będzie można bezpiecznie powtórzyć następującą iterację:

for(key in cleanMap){
 console.log(key + " -> " + newMap [key]);
 // No need to add extra checks, as the object will always be clean
}

Nauczyłem się tej niesamowitej wskazówki tutaj


1
bardziej szczegółowy opis: ryanmorr.com/true-hash-maps-in-javascript
darcher

2

Druga forma (wywoływana w) wylicza nazwy właściwości (lub klucze) obiektu. W każdej iteracji do zmiennej przypisywany jest inny łańcuch nazwy właściwości z obiektu. Zwykle konieczne jest przetestowanie object.hasOwnProperty (zmienna), aby określić, czy nazwa właściwości jest rzeczywiście składową obiektu, czy też została znaleziona w łańcuchu prototypów.

 for (myvar in obj) {
     if (obj.hasOwnProperty(myvar)) { ... } }

(z Javascript Crockforda : Dobre części )


5
inOperator jest inna niż w for-inoświadczeniu.
I Hate Lazy

W rzeczywistości oba są różnymi zastosowaniami słowa kluczowego
Jahan

4
Tak, in to słowo kluczowe. Ale OP pyta o konkretne zastosowanie jako inoperator. Twoja odpowiedź dotyczy innego użycia jako części for-inoświadczenia.
I Hate Lazy

-3

Pierwsza wersja jest krótsza (szczególnie w zminimalizowanym kodzie, w którym zmieniono nazwy zmiennych)

a in b

vs

b.hasOwnProperty(a)

W każdym razie, jak powiedział @AndreMeinhold, nie zawsze dają one ten sam wynik.


1
Byłoby lepiej mieć to jako komentarz. :-)
Hlawuleka MAS
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.