JavaScript instanceof
Aprenda como o operador instanceof do JavaScript funciona, como percorre a cadeia de protótipos e quando usá-lo para verificação de tipos.
Introdução ao Operador instanceof
O operador instanceof em JavaScript é uma ferramenta poderosa para determinar se um object é uma instância de uma classe específica ou de uma função construtora. Ele auxilia os desenvolvedores a verificar o tipo de um object em tempo de execução, facilitando a verificação de tipos e a implementação de polimorfismo de forma eficaz. Esse operador verifica a cadeia de protótipos de um object em relação ao protótipo de uma função construtora, oferecendo um resultado boolean que indica se o object herda do protótipo.
Sintaxe e Uso
A sintaxe do operador instanceof é direta:
object instanceof ConstructorOnde object é o object a ser testado em relação ao Constructor. O operador retorna true se o object for uma instância do Constructor ou tiver herdado dele; caso contrário, retorna false.
Exemplo de Código: Uso Básico
Considere o exemplo a seguir, onde definimos uma classe Vehicle e criamos uma instância dela:
Aplicações Avançadas
Além da verificação básica de tipos, o operador instanceof desempenha um papel fundamental em cenários mais complexos envolvendo herança e polimorfismo. Vamos explorar um cenário com herança:
Exemplo de Código: Herança
Este exemplo ilustra como instanceof confirma que myCar não é apenas uma instância de Car, mas também uma instância de Vehicle, demonstrando a capacidade do operador de reconhecer a cadeia de herança.
Como instanceof Percorre a Cadeia de Protótipos
instanceof não verifica diretamente qual construtor criou o object. Em vez disso, percorre a cadeia de protótipos do object e pergunta: Constructor.prototype aparece em algum lugar dela? Assim que encontra uma correspondência, retorna true; se chegar ao final da cadeia (null) sem encontrar, retorna false.
Por causa disso, você pode alterar um resultado de instanceof reatribuindo a cadeia de protótipos — a verificação é puramente sobre a participação na cadeia, não sobre o construtor que foi executado. Para entender a cadeia em si, consulte Herança prototípica e Sintaxe básica de classe.
Personalizando instanceof com Symbol.hasInstance
Você pode substituir o que obj instanceof Constructor retorna definindo um método estático [Symbol.hasInstance] no construtor. Quando presente, instanceof o chama com o operando do lado esquerdo e usa seu resultado boolean, ignorando completamente a cadeia de protótipos.
Isso é útil para duck-typing — tratar qualquer object que "pareça certo" como membro de um tipo — sem forçá-lo a passar pela hierarquia de classes.
instanceof vs typeof vs constructor
Essas três ferramentas respondem a perguntas diferentes, e escolher a errada é uma fonte comum de bugs.
typeofretorna uma string para categorias de tipos primitivos. É ótimo para primitivos, mas retorna"object"para quase tudo (arrays,null, datas, objetos simples), portanto não consegue distinguir tipos de object.instanceoftesta a participação na cadeia de protótipos e respeita a herança — mas falha entre realms (veja abaixo) e não funciona com primitivos.obj.constructoraponta para a função que criou o object, mas é apenas uma propriedade gravável e reflete apenas a classe mais específica, não toda a cadeia.
Os construtores nativos usados acima são abordados em Protótipos nativos.
A Ressalva de Realm (iframe/window)
Cada contexto de navegação — todo iframe ou janela popup — possui seu próprio conjunto de construtores nativos e seus próprios Array.prototype, Object.prototype e assim por diante. Um array criado em um iframe é um array real, mas não herda do Array.prototype da sua janela. Como resultado, arrayFromIframe instanceof Array retorna false na janela pai, mesmo que o valor seja genuinamente um array. Essa é a razão mais comum pela qual instanceof "mente."
Para valores que podem cruzar realms, prefira verificações agnósticas de realm como Array.isArray(value).
Tags de Tipo Confiáveis com Object.prototype.toString
Quando você precisa de uma verificação de tipo robusta, segura para realm e que também funcione com primitivos, Object.prototype.toString retorna uma string de tag interna no formato [object Type]. Ela não pode ser enganada por protótipos reatribuídos como constructor pode, e funciona entre realms.
Use-a via .call(value) para que o valor se torne this. Uma classe pode até controlar sua própria tag com a propriedade Symbol.toStringTag.
Boas Práticas e Considerações
Embora o operador instanceof seja inestimável, é essencial usá-lo com critério:
- Sensibilidade à Cadeia de Protótipos: O operador
instanceofdepende da cadeia de protótipos, o que significa que alterações no protótipo de um object podem afetar o resultado das verificações cominstanceof. - Uso em Polimorfismo: É particularmente útil em cenários onde o comportamento polimórfico é desejado, permitindo um código flexível que pode lidar com objects de diferentes tipos de maneira unificada.
- Problemas entre Frames: Tenha cuidado ao usar
instanceofcom objects provenientes de diferentes contextos JavaScript (por exemplo, iframes ou diferentes janelas), pois cada contexto possui sua própria cadeia de protótipos exclusiva.
Exemplo Prático: Polimorfismo
Veja como você pode usar instanceof para implementar comportamento polimórfico:
Conclusão
Compreender e utilizar efetivamente o operador instanceof é fundamental para dominar os aspectos de programação orientada a objetos do JavaScript. Ele não apenas auxilia na verificação de tipos e na garantia da correção do seu código, mas também permite escrever um código mais flexível e de fácil manutenção por meio do polimorfismo. Ao integrar o operador instanceof de forma inteligente nas suas práticas de desenvolvimento, você pode aprimorar significativamente a robustez e a escalabilidade das suas aplicações JavaScript.