What is the instanceof operator in JavaScript?
javascript中的
- 这是怎么一回事?
- 它能解决什么问题?
- 什么时候合适,什么时候不合适?
运算符
左侧(lhs)操作数是测试到右侧(rhs)操作数的实际对象,后者是类的实际构造函数。基本定义是:
1 2 | Checks the current object and returns true if the object is of the specified object type. |
下面是一些很好的例子,下面是直接从Mozilla的开发人员网站上获取的一个例子:
1 2 3 4 | 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) |
值得一提的是,如果对象继承自类的原型,那么
1 2 | var p = new Person("Jon"); p instanceof Person |
这是因为
我添加了一个带有一些示例代码和解释的小示例。
当你声明一个变量时,你给它一个特定的类型。
例如:
1 2 3 | int i; float f; Customer c; |
上面显示了一些变量,即
上面我们已经看到,
真的很简单!
到目前为止,这一例子有一个重要的方面似乎还没有被任何评论所涵盖:继承。由于原型继承,使用instanceof评估的变量可能会为多个"类型"返回true。
例如,让我们定义类型和子类型:
1 2 3 4 5 6 7 8 9 10 11 12 | 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 |
现在我们有了几个"类",让我们创建一些实例,并找出它们是什么实例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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 |
看到最后一行了吗?对函数的所有"new"调用都返回从对象继承的对象。即使使用对象创建速记法,这也是正确的:
1 2 3 4 | alert( "Q: Is {} an instance of Object?" + "A:" + ( {} instanceof Object ) ); // -> true |
"类"定义本身又如何呢?它们是什么实例?
1 2 3 4 5 6 7 8 9 | 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 |
我认为理解任何对象都可以是多种类型的实例是很重要的,因为您(错误地)假设可以使用
如果您使用的是任何继承模式,并且希望通过duck类型以外的方法来确认对象的子代,那么这一点也很重要。
希望能帮助任何人探索
这里的其他答案是正确的,但他们不了解
javascript中的每个对象都有一个原型,可以通过
1 2 3 4 5 6 7 8 9 10 11 | 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__; } } |
这基本上是对ECMA-262第5.1版(也称为ES5)第15.3.5.3节的解释。
注意,可以将任何对象重新分配给函数的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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 |
我认为值得注意的是,instanceof是通过在声明对象时使用"new"关键字定义的。在Jonh的例子中;
1 2 3 4 | var color1 = new String("green"); color1 instanceof String; // returns true var color2 ="coral"; color2 instanceof String; // returns false (color2 is not a String object) |
他没有提到的是这个;
1 2 | var color1 = String("green"); color1 instanceof String; // returns false |
指定"new"实际上将字符串构造函数函数的结束状态复制到了color1变量中,而不仅仅是将其设置为返回值。我认为这更好地显示了新关键字的作用;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 #<Test> has no method 'test' test // returns 'test' |
使用"new"将函数内部的"this"值分配给声明的var,而不使用它将分配返回值。
您可以使用它进行错误处理和调试,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 | try{ somefunction(); } catch(error){ if (error instanceof TypeError) { // Handle type Error } else if (error instanceof ReferenceError) { // Handle ReferenceError } else { // Handle all other error types } } |
1 2 3 4 5 6 7 8 9 10 | //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); |
What is it?
javascript是一种原型语言,这意味着它使用原型进行"继承"。
1 | obj instanceof testObj; |
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 | function Person(name) { this.name = name; } var me = new Person('Willem'); console.log(me instanceof Person); // true // because: me.__proto__ === Person.prototype // evaluates true console.log(me instanceof Object); // true // because: me.__proto__.__proto__ === Object.prototype // evaluates true console.log(me instanceof Array); // false // because: Array is nowhere on the prototype chain |
What problems does it solve?
它解决了方便地检查对象是否来自某个原型的问题。例如,当一个函数接收到一个可以有各种原型的对象时。然后,在使用原型链中的方法之前,我们可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | function Person1 (name) { this.name = name; } function Person2 (name) { this.name = name; } Person1.prototype.talkP1 = function () { console.log('Person 1 talking'); } Person2.prototype.talkP2 = function () { console.log('Person 2 talking'); } function talk (person) { if (person instanceof Person1) { person.talkP1(); } if (person instanceof Person2) { person.talkP2(); } } const pers1 = new Person1 ('p1'); const pers2 = new Person2 ('p2'); talk(pers1); talk(pers2); |
在这里,首先检查
When is it appropriate and when not?
我们已经讨论过了。当你需要检查一个对象的原型时,可以在使用它之前使用它。
构造函数只是一个普通函数。严格地说,它是一个函数对象,因为在JavaScript中,一切都是一个对象。这个函数对象有一个原型,因为每个函数都有一个原型。
原型只是一个普通的对象,它位于另一个对象的原型链中。这意味着,在另一个对象的原型链中,对象将成为原型:
1 2 3 4 5 6 7 8 9 | 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 |
应该避免使用
关于"什么时候合适,什么时候不合适?"我的2分钱:
我刚找到一个真实的应用程序,我想现在会更频繁地使用它。
如果使用jquery事件,有时您希望编写一个更通用的函数,该函数也可以直接调用(不带事件)。您可以使用
1 2 3 4 5 6 7 8 9 | 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 |
在我的例子中,函数需要计算所有的东西(通过按钮上的单击事件)或者只计算一个特定的元素。我使用的代码:
1 2 3 4 | var recalc = function (el) { el = (el == undefined || el instanceof $.Event) ? $('span.allItems') : $(el); // calculate... }; |