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))
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:
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à).
({foo:"bar"}).hasOwnProperty("toString")vs"toString" in ({foo:"bar"})
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.
incontrollerà anche le proprietà ereditate, che non è il caso hasOwnProperty.
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.
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
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 )
inoperatore è diverso for-indall'istruzione.
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.
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.
in will also return true if key gets found somewhere in the prototype chain. puoi scrivere un esempio? Grazie.