Pesquisa de site

javascript - se(chave em objeto) ou se(objeto.hasOwnProperty(chave))


As duas afirmações a seguir produzem a mesma saída? Existe algum motivo para preferir uma forma em vez da outra?

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

Resposta #1

Tenha cuidado - eles não produzirão o mesmo resultado.

in também retornará true se key for encontrado em algum lugar na cadeia de protótipos, enquanto Object.hasOwnProperty (como o próprio nome já nos diz), retornará true apenas se key estiver disponível diretamente naquele objeto (ou seja, ele "possui" a propriedade).

Resposta #2

Vou tentar explicar com outro exemplo. Digamos que tenhamos o seguinte objeto com duas propriedades:

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

Vamos criar uma instância de TestObj:

var o = new TestObj();

Vamos examinar a instância do objeto:

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

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

Conclusão:

  • o operador in retorna verdadeiro sempre, se a propriedade for acessível pelo objeto, diretamente ou a partir do protótipo

  • hasOwnProperty() retorna verdadeiro apenas se a propriedade existir na instância, mas não no seu protótipo

Se quisermos verificar se alguma propriedade existe no protótipo, logicamente, diríamos:

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

Finalmente :

Então, em relação à afirmação de que essas duas condições ...

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

...produzir o mesmo resultado, a resposta é óbvia, depende.

Resposta #3

in também verificará propriedades herdadas, o que não ocorre com hasOwnProperty.

Resposta #4

Em resumo, hasOwnProperty() não verifica o protótipo, enquanto in verifica o protótipo.

Retirado de O'Reilly High Performance Javascript:

Você pode determinar se um objeto possui um membro de instância com um determinado nome usando o método hasOwnProperty() e passando o nome do membro. Para determinar se um objeto tem acesso a uma propriedade com um determinado nome, você pode usar o operador in. Por exemplo:

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

Neste código, hasOwnProperty() retorna true quando "title" é passado porque title é uma instância de objeto; o método retorna false quando "toString" é passado porque ele não existe na instância. Quando cada nome de propriedade é usado com o operador in, o resultado é true em ambas as vezes porque ele procura na instância e no protótipo.

Resposta #5

Você conseguiu algumas respostas realmente ótimas. Eu só quero oferecer algo que vai poupar você da necessidade de verificar "hasOwnProperty" enquanto itera sobre um objeto.

Ao criar um objeto, geralmente as pessoas o criam desta maneira:

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

Agora, se você quiser iterar através de "someMap", você terá que fazer desta maneira:

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

Estamos fazendo isso para evitar iterar sobre propriedades herdadas.

Se você pretende criar um objeto simples que será usado apenas como um "mapa" (ou seja, pares de chave-valor), você pode fazer isso assim:

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

Então agora será seguro iterar assim:

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

Eu aprendi essa dica incrível aqui

Artigos relacionados