As duas instruções a seguir produzem a mesma saída? Existe alguma razão para preferir um caminho para o outro?
if (key in object)
if (object.hasOwnProperty(key))
As duas instruções a seguir produzem a mesma saída? Existe alguma razão para preferir um caminho para o outro?
if (key in object)
if (object.hasOwnProperty(key))
Respostas:
Tenha cuidado - eles não produzirão o mesmo resultado.
intambém retornará truese keyfor encontrado em algum lugar da cadeia de protótipos , enquanto que Object.hasOwnProperty(como o nome já nos diz), retornará apenas truese keyestiver disponível diretamente nesse objeto (seu "possui" a propriedade).
({foo:"bar"}).hasOwnProperty("toString")vs"toString" in ({foo:"bar"})
Vou tentar explicar com outro exemplo. Digamos que temos o seguinte objeto com duas propriedades:
function TestObj(){
this.name = 'Dragon';
}
TestObj.prototype.gender = 'male';
Vamos criar uma instância do 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 true sempre, se a propriedade estiver acessível pelo objeto, diretamente ou a partir do protótipo
hasOwnProperty () retorna true somente se a propriedade existir na instância, mas não em seu protótipo
Se quisermos verificar se existe alguma propriedade 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, com relação à afirmação de que essas duas condições ...
if (key in object)
if (object.hasOwnProperty(key))
... produz o mesmo resultado, a resposta é óbvia, depende.
intambém verificará propriedades herdadas, o que não é o caso hasOwnProperty.
Em resumo, hasOwnProperty()não procura no protótipo enquanto inprocura no protótipo.
Retirado do O'Reilly High Performance Javascript :
Você pode determinar se um objeto tem um membro da instância com um nome especificado 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
Nesse código, hasOwnProperty () retorna true quando "title" é passado porque title é uma instância de objeto; o método retorna false quando "toString" é passado porque não existe na instância. Quando cada nome de propriedade é usado com o operador in, o resultado é verdadeiro duas vezes, porque pesquisa a instância e o protótipo.
Você tem ótimas respostas. Eu só quero oferecer algo que poupe a necessidade de verificar "hasOwnProperty" enquanto itera 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 percorrer "someMap", precisará fazer o seguinte:
const key
for(key in someMap ){
if (someMap.hasOwnProperty(key)) {
// Do something
}
}
Estamos fazendo isso para evitar a iteração sobre propriedades herdadas.
Se você pretende criar um objeto simples que será usado apenas como um "mapa" (ou seja, pares de chave-valor), faça o seguinte:
const newMap = Object.create(null);
// Now, newMap won't have prototype at all.
// newMap.constructor will yield -> undefined
Portanto, 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
O outro formulário (chamado in) enumera os nomes (ou chaves) de propriedades de um objeto. Em cada iteração, outra string de nome de propriedade do objeto é atribuída à variável. Geralmente é necessário testar object.hasOwnProperty (variável) para determinar se o nome da propriedade é realmente um membro do objeto ou foi encontrado na cadeia de protótipos.
for (myvar in obj) {
if (obj.hasOwnProperty(myvar)) { ... } }
(do Javascript de Crockford : The Good Parts )
inoperador é diferente da for-indeclaração.
iné uma palavra-chave. Mas o OP está perguntando sobre o uso específico como inoperador. Sua resposta lida com o outro uso como parte da for-indeclaração.
A primeira versão é mais curta (especialmente no código minificado, onde as variáveis são renomeadas)
a in b
vs
b.hasOwnProperty(a)
De qualquer forma, como o @AndreMeinhold disse, eles nem sempre produzem o mesmo resultado.
in will also return true if key gets found somewhere in the prototype chain? você pode escrever um exemplo? obrigado.