if (chiave nell'oggetto) o if (object.hasOwnProperty (chiave)


173

Le seguenti due istruzioni producono lo stesso output? C'è qualche motivo per preferire un modo all'altro?

 if (key in object)

 if (object.hasOwnProperty(key))

Risposte:


181

Fai attenzione: non produrranno lo stesso risultato.

inrestituirà anche truese keyviene trovato da qualche parte nella catena del prototipo , mentre Object.hasOwnProperty(come già il nome ci dice), restituirà solo truese keyè disponibile direttamente su quell'oggetto ("possiede" la proprietà).


3
cosa intendi esattamente per in will also return true if key gets found somewhere in the prototype chain. puoi scrivere un esempio? Grazie.
Lorraine Bernard,

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

68

Proverò a spiegare con un altro esempio. Supponiamo che abbiamo il seguente oggetto con due proprietà:

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

Creiamo un'istanza di TestObj:

var o = new TestObj();

Esaminiamo l'istanza dell'oggetto:

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

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

Conclusione:

  • in operator restituisce true sempre, se la proprietà è accessibile dall'oggetto, direttamente o dal prototipo

  • hasOwnProperty () restituisce true solo se esiste proprietà sull'istanza, ma non sul suo prototipo

Se vogliamo verificare l'esistenza di alcune proprietà sul prototipo, logicamente, dovremmo dire:

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

Finalmente:

Quindi, per quanto riguarda l'affermazione che queste due condizioni ...

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

... produce lo stesso risultato, la risposta è ovvia, dipende.


28

incontrollerà anche le proprietà ereditate, che non è il caso hasOwnProperty.


25

In sintesi, hasOwnProperty()non guarda nel prototipo mentre inguarda nel prototipo.

Tratto da O'Reilly High Performance Javascript :

È possibile determinare se un oggetto ha un membro di istanza con un determinato nome utilizzando il metodo hasOwnProperty () e passando il nome del membro. Per determinare se un oggetto ha accesso a una proprietà con un determinato nome, è possibile utilizzare l'operatore in. Per esempio:

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 questo codice, hasOwnProperty () restituisce true quando viene passato "title" perché title è un'istanza di oggetto; il metodo restituisce false quando viene passato "toString" perché non esiste sull'istanza. Quando ogni nome di proprietà viene utilizzato con l'operatore in, il risultato è vero entrambe le volte perché cerca l'istanza e il prototipo.


5

Hai delle risposte davvero fantastiche. Voglio solo offrire qualcosa che ti salverà la necessità di controllare "hasOwnProperty" durante l'iterazione di un oggetto.

Quando si crea un oggetto, di solito le persone lo creano in questo modo:

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

Ora, se vuoi iterare attraverso "someMap" dovrai farlo in questo modo:

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

Lo stiamo facendo per evitare di ripetere le proprietà ereditate.

Se si intende creare un oggetto semplice che verrà utilizzato solo come "mappa" (ovvero coppie chiave-valore), è possibile farlo in questo modo:

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

Quindi ora sarà sicuro iterare in questo modo:

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

Ho imparato questo fantastico suggerimento qui


1
un articolo più dettagliato: ryanmorr.com/true-hash-maps-in-javascript
darcher,

2

L'altro modulo (chiamato per in) enumera i nomi delle proprietà (o le chiavi) di un oggetto. Ad ogni iterazione, alla stringa viene assegnata un'altra stringa di nome proprietà dall'oggetto. Di solito è necessario testare object.hasOwnProperty (variabile) per determinare se il nome della proprietà è veramente un membro dell'oggetto o è stato trovato invece nella catena di prototipi.

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

(dal Javascript di Crockford : Le parti buone )


5
L' inoperatore è diverso for-indall'istruzione.
Odio pigro il

In realtà entrambi sono usi diversi nella parola chiave
Jahan

4
Sì, inè una parola chiave. Ma OP sta chiedendo l'utilizzo specifico come inoperatore. La tua risposta riguarda l'altro utilizzo come parte for-indell'istruzione.
Odio Lazy il

-3

La prima versione è più corta (specialmente nel codice minimizzato in cui le variabili vengono rinominate)

a in b

vs

b.hasOwnProperty(a)

Comunque, come ha detto @AndreMeinhold, non sempre producono lo stesso risultato.


1
Sarebbe stato meglio avere questo come commento. :-)
Hlawuleka MAS
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.