if (Objekt eingeben) oder if (object.hasOwnProperty (Schlüssel)

173

Erzeugen die folgenden beiden Anweisungen dieselbe Ausgabe? Gibt es einen Grund, einen Weg dem anderen vorzuziehen?

 if (key in object)

 if (object.hasOwnProperty(key))
Lorraine Bernard
quelle

Antworten:

181

Seien Sie vorsichtig - sie werden nicht das gleiche Ergebnis erzielen.

inwird auch zurückgegeben, truewenn keyes irgendwo in der Prototypenkette gefunden wird , wohingegen Object.hasOwnProperty(wie der Name bereits sagt) nur zurückgegeben wird, truewenn keyes für dieses Objekt direkt verfügbar ist (es "besitzt" die Eigenschaft).

Andre Meinhold
quelle
3
was meinst du genau für in will also return true if key gets found somewhere in the prototype chain. Kannst du ein Beispiel schreiben? Vielen Dank.
Lorraine Bernard
44
@ Lor: ({foo:"bar"}).hasOwnProperty("toString")vs"toString" in ({foo:"bar"})
Ich hasse faul
68

Ich werde versuchen, es mit einem anderen Beispiel zu erklären. Angenommen, wir haben das folgende Objekt mit zwei Eigenschaften:

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

Erstellen wir eine Instanz von TestObj:

var o = new TestObj();

Lassen Sie uns die Objektinstanz untersuchen:

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

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

Fazit:

  • Der Operator in gibt immer true zurück, wenn das Objekt direkt oder vom Prototyp aus auf die Eigenschaft zugreifen kann

  • hasOwnProperty () gibt nur dann true zurück, wenn eine Eigenschaft für die Instanz vorhanden ist, nicht jedoch für ihren Prototyp

Wenn wir logischerweise überprüfen möchten, ob auf dem Prototyp eine Eigenschaft vorhanden ist, würden wir sagen:

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

Schließlich:

Also, in Bezug auf die Aussage, dass diese beiden Bedingungen ...

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

... das gleiche Ergebnis erzielen, die Antwort liegt auf der Hand, es kommt darauf an.

Dalibor
quelle
28

inprüft auch auf geerbte Eigenschaften, was bei nicht der Fall ist hasOwnProperty.

xavier.seignard
quelle
25

Zusammenfassend hasOwnProperty()sieht es nicht im Prototyp aus, während ines im Prototyp aussieht.

Entnommen aus O'Reilly High Performance Javascript :

Sie können mithilfe der Methode hasOwnProperty () und der Übergabe des Namens des Mitglieds bestimmen, ob ein Objekt ein Instanzmitglied mit einem bestimmten Namen hat. Um festzustellen, ob ein Objekt Zugriff auf eine Eigenschaft mit einem bestimmten Namen hat, können Sie den Operator in verwenden. Beispielsweise:

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

In diesem Code gibt hasOwnProperty () true zurück, wenn "title" übergeben wird, da title eine Objektinstanz ist. Die Methode gibt false zurück, wenn "toString" übergeben wird, da es in der Instanz nicht vorhanden ist. Wenn jeder Eigenschaftsname mit dem Operator in verwendet wird, ist das Ergebnis beide Male wahr, da die Instanz und der Prototyp durchsucht werden.

Etienne Noël
quelle
5

Du hast einige wirklich gute Antworten bekommen. Ich möchte nur etwas anbieten, das Ihnen die Notwendigkeit erspart, "hasOwnProperty" zu überprüfen, während Sie ein Objekt iterieren.

Wenn Sie ein Objekt erstellen, wird es normalerweise folgendermaßen erstellt:

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

Wenn Sie nun "someMap" durchlaufen möchten, müssen Sie dies folgendermaßen tun:

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

Wir tun dies, um zu vermeiden, dass geerbte Eigenschaften wiederholt werden.

Wenn Sie ein einfaches Objekt erstellen möchten, das nur als "Map" (dh Schlüssel-Wert-Paare) verwendet wird, können Sie dies folgendermaßen tun:

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

Jetzt ist es also sicher, so zu iterieren:

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

Ich habe diesen tollen Tipp hier gelernt

Asafel
quelle
1
eine detailliertere Beschreibung: ryanmorr.com/true-hash-maps-in-javascript
darcher
2

Das andere Formular (erforderlich in) listet die Eigenschaftsnamen (oder Schlüssel) eines Objekts auf. Bei jeder Iteration wird der Variablen eine andere Eigenschaftsnamenzeichenfolge aus dem Objekt zugewiesen. In der Regel muss object.hasOwnProperty (Variable) getestet werden, um festzustellen, ob der Eigenschaftsname wirklich ein Mitglied des Objekts ist oder stattdessen in der Prototypenkette gefunden wurde.

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

(aus Crockfords Javascript: The Good Parts )

Jahan
quelle
5
Der inOperator unterscheidet sich von der for-inAnweisung.
Ich hasse faul
Tatsächlich sind beide unterschiedliche Verwendungen von in Schlüsselwörtern
Jahan
4
Ja, inist ein Schlüsselwort. OP fragt jedoch nach der spezifischen Verwendung als inBediener. Ihre Antwort befasst sich mit der anderen Verwendung als Teil der for-inErklärung.
Ich hasse faul
-3

Die erste Version ist kürzer (insbesondere in verkleinertem Code, in dem die Variablen umbenannt werden).

a in b

vs.

b.hasOwnProperty(a)

Wie @AndreMeinhold sagte, führen sie nicht immer zum gleichen Ergebnis.

antonjs
quelle
1
Wäre besser gewesen, dies als Kommentar zu haben. :-)
Hlawuleka MAS