Qual é o operador instanceof em JavaScript? DoCow
instanceof javascript operadores de
A instanceof palavra-chave em JavaScript pode ser bastante confusa quando é encontrada pela primeira vez, já que as pessoas tendem a pensar que o JavaScript não é uma linguagem de programação orientada a objects.
O operando Lado Esquerdo (LHS) é o object real que está sendo testado para o operando Lado Direito (RHS), que é o construtor real de uma class. A definição básica é:
Aqui estão alguns bons exemplos e aqui está um exemplo tirado diretamente do site de desenvolvedor da Mozilla :
var color1 = new String("green"); color1 instanceof String; // returns true var color2 = "coral"; //no type specified color2 instanceof String; // returns false (color2 is not a String object)
Uma coisa que vale a pena mencionar é instanceof avalia como true se o object herda do protótipo da class:
var p = new Person("Jon"); p instanceof Person
Isso é p instanceof Person é true desde que p herda de Person.prototype .
Por solicitação do OP
Eu adicionei um pequeno exemplo com algum código de exemplo e uma explicação.
Quando você declara uma variável, você atribui um tipo específico.
int i; float f; Customer c;
Os itens acima mostram algumas variables, a saber, i , f e c . Os tipos são integer , float e um tipo de dados do Customer definido pelo usuário. Tipos como os acima podem ser para qualquer idioma, não apenas JavaScript. No entanto, com JavaScript quando você declara uma variável que não define explicitamente um tipo, var x , x pode ser um tipo de dados definido pelo número / string / um usuário. Então, o que o instanceof faz é verificar o object para ver se ele é do tipo especificado, de modo que, tomando o object Customer , poderíamos fazer o seguinte:
var c = new Customer(); c instanceof Customer; //Returns true as c is just a customer c instanceof String; //Returns false as c is not a string, it's a customer silly!
Acima nós vimos que c foi declarado com o tipo Customer . Nós o fizemos de novo e verificamos se é do tipo Customer ou não. Claro que é verdade. Então, ainda usando o object Customer , verificamos se é uma String . Não, definitivamente não é um String nós criamos um object Customer não um object String . Nesse caso, retorna false.
Há uma faceta importante para o exemplo, que parece não estar coberta em nenhum dos comentários até agora: inheritance. Uma variável sendo avaliada pelo uso de instanceof poderia retornar true para vários "tipos" devido à inheritance prototypal.
Por exemplo, vamos definir um tipo e um subtipo:
function Foo(){ //a Foo constructor //assign some props return this; } function SubFoo(){ //a SubFoo constructor Foo.call( this ); //inherit static props //assign some new props return this; } SubFoo.prototype = new Foo(); // Inherit prototype
Agora que temos algumas "classs", vamos criar algumas instâncias e descobrir quais são as instâncias de:
var foo = new Foo() , subfoo = new SubFoo() ; alert( "Q: Is foo an instance of Foo? " + "A: " + ( foo instanceof Foo ) ); // -> true alert( "Q: Is foo an instance of SubFoo? " + "A: " + ( foo instanceof SubFoo ) ); // -> false alert( "Q: Is subfoo an instance of Foo? " + "A: " + ( subfoo instanceof Foo ) ); // -> true alert( "Q: Is subfoo an instance of SubFoo? " + "A: " + ( subfoo instanceof SubFoo ) ); // -> true alert( "Q: Is subfoo an instance of Object? " + "A: " + ( subfoo instanceof Object ) ); // -> true
Veja essa última linha? Todas as chamadas "novas" para uma function retornam um object que herda de Object. Isso vale mesmo quando se usa a abreviação de criação de object:
alert( "Q: Is {} an instance of Object? " + "A: " + ( {} instanceof Object ) ); // -> true
E as próprias definições de "class"? Quais são as instâncias de?
alert( "Q: Is Foo an instance of Object? " + "A:" + ( Foo instanceof Object) ); // -> true alert( "Q: Is Foo an instance of Function? " + "A:" + ( Foo instanceof Function) ); // -> true
Eu sinto que entender que qualquer object pode ser uma instância de tipos MÚLTIPLOS é importante, já que você assume (incorretamente) que você poderia diferenciar entre, digamos e object e uma function pelo uso de instanceof . Como este último exemplo mostra claramente que uma function é um object.
Isso também é importante se você estiver usando algum padrão de inheritance e quiser confirmar a progênie de um object por outros methods além da tipagem de pato.
Espero que ajude alguém a explorar o instanceof .
As outras respostas aqui estão corretas, mas elas não entendem como o instanceof realmente funciona, o que pode interessar a alguns advogados linguísticos por aí.
Todo object em JavaScript possui um protótipo, acessível através da propriedade __proto__ . As funções também possuem uma propriedade prototype , que é o __proto__ inicial para qualquer object criado por elas. Quando uma function é criada, ela recebe um object exclusivo para o prototype . O operador instanceof usa essa exclusividade para fornecer uma resposta. Aqui está o instanceof aparência se você escreveu como uma function.
function instance_of(V, F) { var O = F.prototype; V = V.__proto__; while (true) { if (V === null) return false; if (O === V) return true; V = V.__proto__; } }
Isso é basicamente parafraseando a edição 5.1 do ECMA-262 (também conhecida como ES5), seção 15.3.5.3.
Observe que você pode reatribuir qualquer object à propriedade prototype uma function e pode reatribuir a propriedade __proto__ um object depois que ela for construída. Isto lhe dará alguns resultados interessantes:
function F() { } function G() { } var p = {}; F.prototype = p; G.prototype = p; var f = new F(); var g = new G(); f instanceof F; // returns true f instanceof G; // returns true g instanceof F; // returns true g instanceof G; // returns true F.prototype = {}; f instanceof F; // returns false g.__proto__ = {}; g instanceof G; // returns false
Eu acho que vale a pena notar que instanceof é definido pelo uso da palavra-chave "new" ao declarar o object. No exemplo de JonH;
O que ele não mencionou é isso;
var color1 = String("green"); color1 instanceof String; // returns false
Especificar "novo" realmente copiou o estado final da function do construtor String para o color1 var, em vez de apenas configurá-lo para o valor de retorno. Acho que isso mostra melhor o que a nova palavra-chave faz;
function Test(name){ this.test = function(){ return 'This will only work through the "new" keyword.'; } return name; } var test = new Test('test'); test.test(); // returns 'This will only work through the "new" keyword.' test // returns the instance object of the Test() function. var test = Test('test'); test.test(); // throws TypeError: Object # has no method 'test' test // returns 'test'
Usando "novo" atribui o valor de "isto" dentro da function ao var declarado, enquanto não o utiliza, atribui o valor de retorno.
E você pode usá-lo para tratamento de erros e debugging, como este:
try{ somefunction(); } catch(error){ if (error instanceof TypeError) { // Handle type Error } else if (error instanceof ReferenceError) { // Handle ReferenceError } else { // Handle all other error types } }
//Vehicle is a function. But by naming conventions //(first letter is uppercase), it is also an object //constructor function ("class"). function Vehicle(numWheels) { this.numWheels = numWheels; } //We can create new instances and check their types. myRoadster = new Vehicle(4); alert(myRoadster instanceof Vehicle);
Sobre a questão "Quando é apropriado e quando não?", Meus 2 centavos:
instanceof raramente é útil no código de produção, mas é útil em testes em que você deseja afirmar que seu código retorna / cria objects dos tipos corretos. Ao ser explícito sobre os tipos de objects que seu código está retornando / criando, seus testes se tornam mais poderosos como uma ferramenta para entender e documentar seu código.
instanceof é apenas açúcar sintático para isPrototypeOf :
function Ctor() {} var o = new Ctor(); o instanceof Ctor; // true Ctor.prototype.isPrototypeOf(o); // true o instanceof Ctor === Ctor.prototype.isPrototypeOf(o); // equivalent
instanceof depende apenas do protótipo de um construtor de um object.
Um construtor é apenas uma function normal. Estritamente falando, é um object de function, já que tudo é um object em JavaScript. E esse object de function tem um protótipo, porque toda function tem um protótipo.
Um protótipo é apenas um object normal, localizado dentro da cadeia de protótipos de outro object. Isso significa estar na cadeia de protótipos de outro object que faz um object para um protótipo:
function f() {} // ordinary function var o = {}, // ordinary object p; f.prototype = o; // oops, o is a prototype now p = new f(); // oops, f is a constructor now o.isPrototypeOf(p); // true p instanceof f; // true
O operador instanceof deve ser evitado porque falsifica classs, que não existem em Javascript. Apesar da palavra-chave class não no ES2015, uma vez que a class é novamente apenas açúcar sintático para … mas isso é outra história.
Acabei de encontrar uma aplicação do mundo real e vou usá-lo com mais freqüência agora, eu acho.
Se você usa events jQuery, às vezes você quer escrever uma function mais genérica que também pode ser chamada diretamente (sem evento). Você pode usar instanceof para verificar se o primeiro parâmetro de sua function é uma instância de jQuery.Event e reagir apropriadamente.
var myFunction = function (el) { if (el instanceof $.Event) // event specific code else // generic code }; $('button').click(recalc); // Will execute event specific code recalc('myParameter'); // Will execute generic code
No meu caso, a function necessária para calcular algo para todos (via evento de clique em um botão) ou apenas um elemento específico. O código que usei:
var recalc = function (el) { el = (el == undefined || el instanceof $.Event) ? $('span.allItems') : $(el); // calculate... };