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))
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:
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ść).
({foo:"bar"}).hasOwnProperty("toString")vs"toString" in ({foo:"bar"})
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.
insprawdzi również dziedziczone właściwości, co nie ma miejsca w przypadku hasOwnProperty.
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.
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
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 )
inOperator jest inna niż w for-inoświadczeniu.
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.
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.
in will also return true if key gets found somewhere in the prototype chain. czy możesz napisać przykład? dzięki.