JavaScript 中的instanceof 运算符是什么?
JavaScript 中的 instanceof
关键字在第一次遇到时可能会很令人困惑,因为人们倾向于认为 JavaScript 不是面向对象的编程语言。
- 它是什么?
- 它解决什么问题?
- 什么时候合适,什么时候不合适?
The instanceof
keyword in JavaScript can be quite confusing when it is first encountered, as people tend to think that JavaScript is not an object-oriented programming language.
- What is it?
- What problems does it solve?
- When is it appropriate and when not?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
instanceof
左侧 (LHS) 操作数是正在测试右侧 (RHS) 操作数的实际对象,右侧操作数是类的实际构造函数。基本定义是:
这里有一些很好的例子,这是一个示例直接取自 Mozilla 开发者网站:
值得一提的是如果对象继承自类的原型,则
instanceof
的值为 true:即
p instanceof Person
为 true,因为p
继承自Person。原型
。根据OP的要求,
I've added a small example with some sample code and an explanation.
当您声明变量时,您会为其指定特定类型。
例如:
上面显示了一些变量,即
i
、f
和c
。这些类型包括integer
、float
和用户定义的Customer
数据类型。诸如上述的类型可以适用于任何语言,而不仅仅是 JavaScript。但是,使用 JavaScript,当您声明变量时,您不会显式定义类型,var x
,x 可以是数字/字符串/用户定义的数据类型。所以instanceof
所做的是检查对象以查看它是否属于指定的类型,因此从上面获取Customer
对象我们可以这样做:上面我们已经看到 < code>c 是用
Customer
类型声明的。我们对其进行了新建并检查它是否属于Customer
类型。当然是,它返回 true。然后仍然使用Customer
对象检查它是否是String
。不,绝对不是String
我们新建了一个Customer
对象,而不是String
对象。在这种情况下,它返回 false。真的就是这么简单!
instanceof
The Left Hand Side (LHS) operand is the actual object being tested to the Right Hand Side (RHS) operand which is the actual constructor of a class. The basic definition is:
Here are some good examples and here is an example taken directly from Mozilla's developer site:
One thing worth mentioning is
instanceof
evaluates to true if the object inherits from the class's prototype:That is
p instanceof Person
is true sincep
inherits fromPerson.prototype
.Per the OP's request
I've added a small example with some sample code and an explanation.
When you declare a variable you give it a specific type.
For instance:
The above show you some variables, namely
i
,f
, andc
. The types areinteger
,float
and a user definedCustomer
data type. Types such as the above could be for any language, not just JavaScript. However, with JavaScript when you declare a variable you don't explicitly define a type,var x
, x could be a number / string / a user defined data type. So whatinstanceof
does is it checks the object to see if it is of the type specified so from above taking theCustomer
object we could do:Above we've seen that
c
was declared with the typeCustomer
. We've new'd it and checked whether it is of typeCustomer
or not. Sure is, it returns true. Then still using theCustomer
object we check if it is aString
. Nope, definitely not aString
we newed aCustomer
object not aString
object. In this case, it returns false.It really is that simple!
到目前为止,instanceof 有一个重要的方面似乎没有在任何评论中涉及:继承。由于原型继承,使用 instanceof 计算的变量可能会针对多个“类型”返回 true。
例如,让我们定义一个类型和一个子类型:
现在我们有几个“类”,让我们创建一些实例,并找出它们的实例:
看到最后一行了吗?对函数的所有“新”调用都会返回一个继承自 Object 的对象。即使使用对象创建简写也是如此:
“类”定义本身又如何呢?它们是什么实例?
我觉得理解任何对象都可以是多个类型的实例很重要,因为您可能(错误地)假设您可以通过使用
instanceof
来区分对象和函数。最后一个例子清楚地表明函数是一个对象。如果您正在使用任何继承模式并且想要通过鸭子类型以外的方法确认对象的后代,这一点也很重要。
There's an important facet to instanceof that does not seem to be covered in any of the comments thus far: inheritance. A variable being evaluated by use of instanceof could return true for multiple "types" due to prototypal inheritance.
For example, let's define a type and a subtype:
Now that we have a couple of "classes" lets make some instances, and find out what they're instances of:
See that last line? All "new" calls to a function return an object that inherits from Object. This holds true even when using object creation shorthand:
And what about the "class" definitions themselves? What are they instances of?
I feel that understanding that any object can be an instance of MULTIPLE types is important, since you may (incorrectly) assume that you could differentiate between, say an object and a function by use of
instanceof
. As this last example clearly shows a function is an object.This is also important if you are using any inheritance patterns and want to confirm the progeny of an object by methods other than duck-typing.
这里的其他答案是正确的,但它们没有深入了解
instanceof
的实际工作原理,这可能是一些语言律师感兴趣的。JavaScript 中的每个对象都有一个原型,可以通过 __proto__ 属性访问。函数还有一个prototype属性,它是由函数创建的任何对象的初始__proto__。创建函数时,它会被赋予一个唯一的原型对象。
instanceof
运算符利用这种唯一性为您提供答案。如果将instanceof
编写为函数,则它可能如下所示。这基本上是对 ECMA-262 版本 5.1(也称为 ES5)第 15.3.5.3 节的解释。
请注意,您可以将任何对象重新分配给函数的
prototype
属性,并且可以在构造对象后重新分配对象的__proto__
属性。这会给你一些有趣的结果:The other answers here are correct, but they don't get into how
instanceof
actually works, which may be of interest to some language lawyers out there.Every object in JavaScript has a prototype, accessible through the
__proto__
property. Functions also have aprototype
property, which is the initial__proto__
for any objects created by them. When a function is created, it is given a unique object forprototype
. Theinstanceof
operator uses this uniqueness to give you an answer. Here's whatinstanceof
might look like if you wrote it as a function.This is basically paraphrasing ECMA-262 edition 5.1 (also known as ES5), section 15.3.5.3.
Note that you can reassign any object to a function's
prototype
property, and you can reassign an object's__proto__
property after it is constructed. This will give you some interesting results:我认为值得注意的是,instanceof 是通过在声明对象时使用“new”关键字来定义的。在 JonH 的例子中;
他没有提到的是这个;
指定“new”实际上将 String 构造函数的结束状态复制到 color1 var 中,而不是仅仅将其设置为返回值。我认为这更好地展示了 new 关键字的作用;
使用“new”将函数内“this”的值分配给声明的var,而不使用它则分配返回值。
I think it's worth noting that instanceof is defined by the use of the "new" keyword when declaring the object. In the example from JonH;
What he didn't mention is this;
Specifying "new" actually copied the end state of the String constructor function into the color1 var, rather than just setting it to the return value. I think this better shows what the new keyword does;
Using "new" assigns the value of "this" inside the function to the declared var, while not using it assigns the return value instead.
您可以使用它进行错误处理和调试,如下所示:
And you can use it for error handling and debugging, like this:
Javascript 是一种原型语言,这意味着它使用原型来进行“继承”。
instanceof
运算符测试构造函数的prototype
属性是否存在于对象的__proto__
链中。这意味着它将执行以下操作(假设 testObj 是一个函数对象):obj.__proto__ === testObj.prototype
> ;>如果这是true
instanceof
将返回true
。obj.__proto__.__proto__ === testObj.prototype
>>>如果这是true
instanceof
将返回true
。testObj.prototype
匹配,则instanceof
运算符将返回false
。例子:
它解决了方便地检查对象是否源自某个原型的问题。例如,当一个函数接收一个可以具有各种原型的对象时。然后,在使用原型链中的方法之前,我们可以使用instanceof运算符来检查这些方法是否在对象上。
例子:
在
talk()
函数中,首先检查原型是否位于对象上。之后,选择适当的方法来执行。不进行此检查可能会导致执行不存在的方法,从而导致引用错误。我们已经讨论过这个了。当您需要在使用对象执行某些操作之前检查对象的原型时,请使用它。
Javascript is a prototypal language which means it uses prototypes for 'inheritance'. the
instanceof
operator tests if a constructor function'sprototype
propertype is present in the__proto__
chain of an object. This means that it will do the following (assuming that testObj is a function object):obj.__proto__ === testObj.prototype
>> if this istrue
instanceof
will returntrue
.obj.__proto__.__proto__ === testObj.prototype
>> if this istrue
instanceof
will returntrue
.testObj.prototype
theninstanceof
operator will returnfalse
.Example:
It solved the problem of conveniently checking if an object derives from a certain prototype. For example, when a function recieves an object which can have various prototypes. Then, before using methods from the prototype chain, we can use the
instanceof
operator to check whether the these methods are on the object.Example:
Here in the
talk()
function first is checked if the prototype is located on the object. After this the appropriate method is picked to execute. Not doing this check could result in executing a method which doesn't exist and thus a reference error.We kind of already went over this. Use it when you are in need of checking the prototype of an object before doing something with it.
关于“什么时候合适,什么时候不合适?”这个问题,我的 2 美分:
instanceof
在生产代码中很少有用,但在您想要断言代码返回/创建以下对象的测试中很有用正确的类型。通过明确代码返回/创建的对象类型,您的测试作为理解和记录代码的工具变得更加强大。On the question "When is it appropriate and when not?", my 2 cents:
instanceof
is rarely useful in production code, but useful in tests where you want to assert that your code returns / creates objects of the correct types. By being explicit about the kinds of objects your code is returning / creating, your tests become more powerful as a tool for understanding and documenting your code.我刚刚找到了一个现实世界的应用程序,我想现在会更频繁地使用它。
如果您使用 jQuery 事件,有时您想编写一个更通用的函数,也可以直接调用(没有事件)。您可以使用
instanceof
检查函数的第一个参数是否是jQuery.Event
的实例并做出适当的反应。就我而言,该函数需要计算所有元素(通过按钮上的单击事件)或仅计算一个特定元素。我使用的代码:
I just found a real-world application and will use it more often now, I think.
If you use jQuery events, sometimes you want to write a more generic function which may also be called directly (without event). You can use
instanceof
to check if the first parameter of your function is an instance ofjQuery.Event
and react appropriately.In my case, the function needed to calculate something either for all (via click event on a button) or only one specific element. The code I used:
instanceof
只是isPrototypeOf
的语法糖:instanceof
仅取决于对象构造函数的原型。构造函数只是一个普通的函数。严格来说它是一个函数对象,因为 JavaScript 中一切都是对象。并且这个函数对象有一个原型,因为每个函数都有一个原型。
原型只是一个普通的对象,它位于另一个对象的原型链中。这意味着位于另一个对象的原型链中会使对象成为原型:
应该避免使用
instanceof
运算符,因为它会伪造类,而类在 Javascript 中不存在。尽管 ES2015 中也没有class
关键字,因为class
又只是语法糖......但那是另一个故事了。instanceof
is just syntactic sugar forisPrototypeOf
:instanceof
just depends on the prototype of a constructor of an object.A constructor is just a normal function. Strictly speaking it is a function object, since everything is an object in Javascript. And this function object has a prototype, because every function has a prototype.
A prototype is just a normal object, which is located within the prototype chain of another object. That means being in the prototype chain of another object makes an object to a prototype:
The
instanceof
operator should be avoided because it fakes classes, which do not exist in Javascript. Despite theclass
keyword not in ES2015 either, sinceclass
is again just syntactic sugar for...but that's another story.@SebastianSimon 我的最后一个答案是 8 年前的(当我蹩脚时),我可能写了一些牛*击:)
简单地说 - 目前我使用
instanceof
的唯一情况是当我使用 < code>class 实例和行为取决于我将收到的类,例如。我想区分 404 是 ErrorA(资源不存在)还是 ErrorB(未找到服务) - 库响应代码令人困惑,但幸运的是它使用不同的错误类抛出。绝对(目前)我不会使用它来检查反映基元的类型 - 您无法确定库是否返回
'msg'
或new String('msg ')
。它们都有属于
String
类的方法,因为'msg'
原语在内部包装到字符串对象中。内部意味着通过解释器。它们都是Strings
但instanceof
运算符在这里似乎不够 - 检查是否某物。是原始类型还是类我会使用typeof
&& 的混合instanceof
- 但仅适用于从外部 JS 库返回的内容。当前 TypeScript 正在解决这个问题,您不再需要使用
typeof
和instanceof
进行如此频繁的检查。@SebastianSimon my last answer is 8 years old (when I lamed) and it is possible I wrote some bull*hit :)
Briefly - currently the only cases when I am using
instanceof
is when I am usingclass
instances and behaviour depends on class I will receive, eg. I want to distinct if 404 is ErrorA(resource not exists) or ErrorB(service not found) - library response codes were confusing but for my luck it throwed using different error classes.Definitely (currently) I would NOT use it to check types that reflects primitives - you cannot be sure if library is returning
'msg'
ornew String('msg')
.Both of them have methods that belongs to
String
class because'msg'
primitive is internally wrapped into string object. Internally means by interpreter. They are bothStrings
butinstanceof
operator seems to be insufficient here - to check if sth. is primitive or class I would use mix oftypeof
&&instanceof
- but only for something returned from external JS library.Currenlty TypeScript is solving this problem and you no longer have to use such officious checks with
typeof
andinstanceof
.