typeof 和 instanceof 之间有什么区别?何时应该使用其中之一?
在我的特殊情况下:
callback instanceof Function
或者
typeof callback == "function"
甚至重要,有什么区别?
其他资源:
JavaScript-Garden typeof 与 < a href="http://bonsaiden.github.com/JavaScript-Garden/#types.instanceof" rel="noreferrer">instanceof
In my particular case:
callback instanceof Function
or
typeof callback == "function"
does it even matter, what's the difference?
Additional Resource:
JavaScript-Garden typeof vs instanceof
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(27)
对自定义类型使用
instanceof
:对简单的内置类型使用
typeof
:对复杂的内置类型使用
instanceof
:最后一个有点小有点棘手:
Use
instanceof
for custom types:Use
typeof
for simple built in types:Use
instanceof
for complex built in types:And the last one is a little bit tricky:
两者在功能上很相似,因为它们都返回类型信息,但我个人更喜欢
instanceof
因为它比较实际类型而不是字符串。 类型比较不太容易出现人为错误,而且在技术上速度更快,因为它是比较内存中的指针而不是进行整个字符串比较。Both are similar in functionality because they both return type information, however I personally prefer
instanceof
because it's comparing actual types rather than strings. Type comparison is less prone to human error, and it's technically faster since it's comparing pointers in memory rather than doing whole string comparisons.使用 typeof 的一个很好的理由是变量可能未定义。
使用instanceof 的一个很好的理由是变量可能为空。
所以我认为这实际上取决于您正在检查的可能数据的类型。
A good reason to use typeof is if the variable may be undefined.
A good reason to use instanceof is if the variable may be null.
So really in my opinion it would depend on what type of possible data you are checking.
为了清楚起见,您需要知道两个事实:
Object.setPrototypeOf()
方法 (ECMAScript 2015) 或通过__proto__
属性(旧浏览器,已弃用)显式设置。 但由于性能问题,不建议更改对象的原型。因此instanceof仅适用于对象。 在大多数情况下,您不使用构造函数来创建字符串或数字。 你可以。 但你几乎从不这样做。
另外,instanceof 无法检查到底使用哪个构造函数来创建对象,但会返回 true,即使对象是从被检查的类派生的。 在大多数情况下,这是所需的行为,但有时并非如此。 所以你需要保持这个想法。
另一个问题是不同的作用域有不同的执行环境。 这意味着它们有不同的内置函数(不同的全局对象、不同的构造函数等)。 这可能会导致意想不到的结果。
例如,
[] instanceof window.frames[0].Array
将返回false
,因为Array.prototype !== window.frames[0].Array
和数组继承自前者。此外,它不能用于未定义的值,因为它没有原型。
现在我们来谈谈一件棘手的事情。 如果使用构造函数创建原始类型怎么办?
看起来就像魔法一样。 但事实并非如此。 这就是所谓的装箱(按对象包装原始值)和拆箱(从对象中提取包装的原始值)。 这种代码似乎“有点”脆弱。 当然,您可以避免使用构造函数创建原始类型。 但还有另一种可能的情况,拳击可能会击中你。 当您在基本类型上使用 Function.call() 或 Function.apply() 时。
为了避免这种情况,您可以使用严格模式:
upd:
自 ECMAScript 2015 以来,又多了一种称为 Symbol 的类型,它有自己的 typeof == "symbol"。
您可以在 MDN 上阅读相关内容:(Symbol、typeof)。
To make things clear, you need to know two facts:
Object.setPrototypeOf()
method (ECMAScript 2015) or by the__proto__
property (old browsers, deprecated). Changing the prototype of an object is not recommended though, because of performance issues.Thus instanceof is applicable only to objects. In most cases you aren't using constructors to create strings or numbers. You can. But you almost never do.
Also instanceof can't check, exactly which constructor was used to create the object, but will return true, even if object is derived from class which being checked. In most cases this is the desired behavior, but sometimes it's not. So you need to keep that mind.
Another problem is that different scopes have different execution environments. This means that they have different built-ins (different global object, different constructors, etc.). This may result in unexpected results.
For example,
[] instanceof window.frames[0].Array
will returnfalse
, becauseArray.prototype !== window.frames[0].Array
and arrays inherit from the former.Also, it cannot be used on undefined value, because it don't have a prototype.
Now let's talk about one tricky thing. What if you use constructor to create a primitive type?
Seems like magic. But it is not. It's so-called boxing (wrapping primitive value by object) and unboxing (extracting wrapped primitive value from object). Such kind of code seems to be "a bit" fragile. Of course you can just avoid creating primitive type with constructors. But there is another possible situation, when boxing may hit you. When you use Function.call() or Function.apply() on a primitive type.
To avoiding this you can use strict mode:
upd:
Since ECMAScript 2015, there is one more type called Symbol, which has its own typeof == "symbol".
You can read about it on MDN: (Symbol, typeof).
我在 Safari 5 和 Internet Explorer 9 中发现了一些非常有趣(读作“可怕”)的行为。我在 Chrome 和 Firefox 中使用它并取得了巨大成功。
然后我在IE9下测试,根本就不行。 大惊喜。 但在 Safari 中,它是间歇性的! 于是我开始调试,发现 Internet Explorer总是返回
false
。 但最奇怪的是,Safari 似乎在其 JavaScript VM 中进行了某种优化,第一次是true
,但false
每次你点击重新加载!我的大脑几乎爆炸了。
所以现在我已经决定了:
现在一切都很好。 请注意,您可以调用“a string”.toString(),它只返回字符串的副本,即,
所以从现在开始我将使用两者。
I've discovered some really interesting (read as "horrible") behavior in Safari 5 and Internet Explorer 9. I was using this with great success in Chrome and Firefox.
Then I test in IE9, and it doesn't work at all. Big surprise. But in Safari, it's intermittent! So I start debugging, and I find that Internet Explorer is always returning
false
. But the weirdest thing is that Safari seems to be doing some kind of optimization in its JavaScript VM where it istrue
the first time, butfalse
every time you hit reload!My brain almost exploded.
So now I've settled on this:
And now everything works great. Note that you can call
"a string".toString()
and it just returns a copy of the string, i.e.So I'll be using both from now on.
我认为,当
callback
是Function
的子类型时,instanceof
也可以工作instanceof
also works whencallback
is a subtype ofFunction
, I think其他显着的实际差异:
Other Significant practical differences:
typeof:根据 MDN 文档,typeof 是一个一元运算符,它返回一个字符串,指示未计算的操作数的类型。
对于字符串基元和字符串对象,typeof 返回以下内容:
instanceof:是一个二元运算符,接受一个对象和一个构造函数。 它返回一个布尔值,指示该对象的原型链中是否具有给定的构造函数。
当应用于上面的字符串实例时,并与 String 进行比较,其行为如下:
参考:https://bambielli.com/til/2017-06-18-typeof-vs-instanceof/
typeof: Per the MDN docmentation, typeof is a unary operator that returns a string indicating the type of the unevaluated operand.
In the case of string primitaves and string objects, typeof returns the following:
instanceof: is a binary operator, accepting an object and a constructor. It returns a boolean indicating whether or not the object has the given constructor in its prototype chain.
When applied to the string instances above, and compared to String, it behaves as follows:
Reference: https://bambielli.com/til/2017-06-18-typeof-vs-instanceof/
读完这篇文章后,我得出了一个自我结论,并创建了一个快速参考图表,并在 Chrome 中进行了测试。
可以选取首选单元格(粗体),涉及更简单的用例。
拇指规则:
typeof
myvar === null
myvar === undefined
进行检查Array.isArray([])
进行检查myvar instanceof Object
检查({}).constructor
类似的方式使用代码>或<代码>([]).constructorAfter reading this thread, I came out with a self conclusion and created a quick reference chart, tested in Chrome.
Preferred cells (in bold) can be picked up, involving a simpler usecase.
Thumb Rule:
typeof
myvar === null
myvar === undefined
Array.isArray([])
myvar instanceof Object
({}).constructor
or([]).constructor
Javascript 中的
instanceof
可能很不稳定 - 我相信主要框架都试图避免使用它。 不同的窗口是它可能被破坏的方式之一 - 我相信类层次结构也会混淆它。有更好的方法来测试对象是否是某种内置类型(这通常是您想要的)。 创建实用函数并使用它们:
等等。
instanceof
in Javascript can be flaky - I believe major frameworks try to avoid its use. Different windows is one of the ways in which it can break - I believe class hierarchies can confuse it as well.There are better ways for testing whether an object is a certain built-in type (which is usually what you want). Create utility functions and use them:
And so on.
检查函数时,必须始终使用
typeof
。区别如下:
这就是为什么决不能使用
instanceof
来检查函数的原因。When checking for a function, one must always use
typeof
.Here's the difference:
This is why one must never use
instanceof
to check for a function.这只是对这里所有其他解释的补充知识 - 我不建议在任何地方使用
.constructor
。TL;DR:在
typeof
不可行的情况下,以及当您知道自己不关心原型链时 ,对象。 prototype.constructor
可以是比instanceof
更可行甚至更好的替代方案:它自 1.1 起就已成为标准,因此无需担心向后兼容性。
穆罕默德·乌默 (Muhammad Umer) 也在此处的评论中简要提到了这一点。 它适用于具有原型的所有内容 - 因此所有内容都不是
null
或undefined
:此外,根据您的用例,它可能快很多
instanceof
(原因可能是它不必检查整个原型链)。 就我而言,我需要一种快速方法来检查值是否为类型化数组:https://run.perf.zone/view/isTypedArray-constructor-vs-instanceof-1519140393812
结果:
Chrome 64.0.3282.167(64 位,Windows)
< a href="https://i.sstatic.net/RAsZd.png" rel="nofollow noreferrer">
Firefox 59.0b10(64 位,Windows)
出于好奇,我针对
typeof
做了一个快速玩具基准测试; 令人惊讶的是它的性能并没有差很多,而且在 Chrome 中似乎更快一点:https://run.perf.zone/view/typeof-vs-constructor-string-or-number-1519142623570
注意:函数列出的顺序在图像之间切换!
Chrome 64.0.3282.167(64 位,Windows)
< img src="https://i.sstatic.net/gb4Si.png" alt="String/Number typeof 与构造函数 - Chrome 64.0.3282.167(64 位,Windows)中速度提高 1.26 倍">
< strong>Firefox 59.0b10(64位,Windows)
注意:功能列出的顺序在图像之间切换!
This is just complementary knowledge to all the other explanations here - I am not suggesting to use
.constructor
everywhere.TL;DR: In situations where
typeof
is not an option, and when you know that you do not care about the prototype chain,Object.prototype.constructor
can be a viable or even better alternative thaninstanceof
:It's been in the standard since 1.1, so no worries about backwards compatibility.
Muhammad Umer briefly mentioned this in a comment somewhere here too. It works on everything with a prototype - so everything not
null
orundefined
:Furthermore, depending on your use case it can be a lot faster than
instanceof
(the reason likely being that it doesn't have to check the entire prototype chain). In my case I needed a fast way to check if a value is a typed array:https://run.perf.zone/view/isTypedArray-constructor-vs-instanceof-1519140393812
And the results:
Chrome 64.0.3282.167 (64-bit, Windows)
Firefox 59.0b10 (64-bit, Windows)
Out of curiousity, I did a quick toy benchmark against
typeof
; surprisingly it doesn't perform much worse, and it seems even a bit faster in Chrome:https://run.perf.zone/view/typeof-vs-constructor-string-or-number-1519142623570
NOTE: Order in which functions are listed switches between images!
Chrome 64.0.3282.167 (64-bit, Windows)
Firefox 59.0b10 (64-bit, Windows)
NOTE: Order in which functions are listed switches between images!
instanceof
不适用于基元,例如"foo" instanceof String
将返回false
而typeof "foo" == "string"< /code> 将返回
true
。另一方面,当涉及到自定义对象(或类,无论您想如何称呼它们)时,
typeof
可能不会执行您想要的操作。 例如:碰巧函数既是“函数”基元又是“函数”的实例,这有点奇怪,因为它不像其他基元类型那样工作。
但
instanceof
will not work for primitives eg"foo" instanceof String
will returnfalse
whereastypeof "foo" == "string"
will returntrue
.On the other hand
typeof
will probably not do what you want when it comes to custom objects (or classes, whatever you want to call them). For example:It just so happens that functions are both 'function' primitives and instances of 'Function', which is a bit of an oddity given that it doesn't work like that for other primitive types eg.
but
我建议使用原型的
callback.isFunction()
。他们已经找出了差异,您可以信赖他们的理由。
我想其他 JS 框架也有这样的东西。
我相信
instanceOf
不适用于其他窗口中定义的函数。它们的 Function 与您的
window.Function
不同。I would recommend using prototype's
callback.isFunction()
.They've figured out the difference and you can count on their reason.
I guess other JS frameworks have such things, too.
instanceOf
wouldn't work on functions defined in other windows, I believe.Their Function is different than your
window.Function
.性能
在两者都适用的情况下,
typeof
比instanceof
更快。根据您的引擎,
typeof
的性能差异可能约为 20%。 (您的里程可能会有所不同)以下是
Array
的基准测试:结果
Performance
typeof
is faster thaninstanceof
in situations where both are applicable.Depending on your engine, the performance difference in favor of
typeof
could be around 20%. (Your mileage may vary)Here is a benchmark testing for
Array
:Result
无需被上面的大量示例淹没,只需记住两个观点:
typeof var;
是一个一元运算符,将返回 var 的原始类型或根类型。 这样它将返回原始类型(string
,number
,bigint
,boolean
,undefined 和
symbol
) 或object
类型。如果是更高级别的对象,例如内置对象(String、Number、Boolean、Array..)或复杂或自定义对象,它们都是
object
根类型,但实例基于它们构建的类型是不同的(就像OOP类继承概念),这里a instanceof A
- 一个二元运算符 - 会帮助你,它会通过原型链来检查是否是正确操作数的构造函数(A) 是否出现。因此,每当您想检查“根类型”或使用原始变量时,请使用“typeof”,否则使用“instanceof”。
null
是一种特殊情况,看似原始,但确实是对象的特殊情况。 使用a === null
来检查 null。另一方面,
function
也是一种特殊情况,它是内置对象,但typeof
返回function
,如您所见
instanceof
必须遍历原型链,同时typeof
只需检查一次根类型,因此很容易理解为什么typeof
比instanceof
更快代码>no need to overwhelm with ton of above examples, just keep in mind two points of view:
typeof var;
is an unary operator will return the original type or root type of var. so that it will return primitive types(string
,number
,bigint
,boolean
,undefined
, andsymbol
) orobject
type.in case of higher-level object, like built-in objects (String, Number, Boolean, Array..) or complex or custom objects, all of them is
object
root type, but instance type built base on them is vary(like OOP class inheritance concept), herea instanceof A
- a binary operator - will help you, it will go through the prototype chain to check whether constructor of the right operand(A) appears or not.so whenever you want to check "root type" or work with primitive variable - use "typeof", otherwise using "instanceof".
null
is a special case,which is seemingly primitive, but indeed is a special case for object. Usinga === null
to check null instead.on the other hand,
function
is also a special case, which is built-in object buttypeof
returnfunction
as you can see
instanceof
must go through the prototype chain meanwhiletypeof
just check the root type one time so it's easy to understand whytypeof
is faster thaninstanceof
使用instanceof,因为如果更改类的名称,您将收到编译器错误。
Use instanceof because if you change the name of the class you will get a compiler error.
显着的实际差异:
不要问我为什么。
Significant practical difference:
Don't ask me why.
根据关于 typeof 的 MDN 文档,对象使用“new”关键字实例化的类型为“object”:
而 关于instanceof的文档指出:
因此,如果想要检查某个东西是否是一个字符串,无论它是如何创建的,最安全的方法是使用
instanceof
。According to MDN documentation about typeof, objects instantiated with the "new" keyword are of type 'object':
While documentation about instanceof points that:
So if one wants to check e.g. that something is a string no matter how it was created, safest approach would be to use
instanceof
.非常准确地说
instanceof 应该用于通过构造函数(通常是自定义类型)创建值的地方,例如,
而 typeof 用于检查仅由赋值创建的值,例如
To be very precise
instanceof should be used where value is created via the constructor (generally custom types) for e.g.
whereas typeof to check values created just by assignments for e.g
来自严格的面向对象的教育,我会选择
字符串,因为它很容易出现我糟糕的拼写或其他拼写错误。 另外我觉得它读起来更好。
Coming from a strict OO upbringing I'd go for
Strings are prone to either my awful spelling or other typos. Plus I feel it reads better.
尽管 instanceof 可能比 typeof 快一点,但我更喜欢第二个,因为这种可能的魔力:
Despite instanceof may be a little bit faster then typeof, I prefer second one because of such a possible magic:
另一种情况是,您只能与
instanceof
进行比较 - 它返回 true 或 false。 使用typeof
你可以获取所提供的something的类型One more case is that You only can collate with
instanceof
- it returns true or false. Withtypeof
you can get type of provided something考虑到性能,你最好使用 typeof
使用典型的硬件,如果您创建一个循环 1000 万次迭代的脚本
指令: typeof str == 'string' 将花费 9ms
而 'string' instanceof String 将需要 19ms
with performance in mind, you'd better use typeof
with a typical hardware, if you create a script with a loop of 10 million iterations
the instruction: typeof str == 'string' will take 9ms
while 'string' instanceof String will take 19ms
当然重要......!
让我们通过示例来演示一下。在我们的示例中,我们将以两种不同的方式声明函数。
我们将同时使用
函数声明
和函数构造函数。 我们将了解typeof
和instanceof
在这两种不同场景中的行为方式。使用函数声明创建函数:
对于这种不同结果的可能解释是,当我们进行函数声明时,
typeof
可以理解为它是一个函数。因为typeof
检查 typeof 是否操作的表达式,在我们的例子中MyFunc
已实现是否调用方法。 如果它实现Call
方法,则它是一个函数。否则不是。为了澄清,请检查typeof 的 ecmascript 规范。使用函数构造函数创建函数:
这里
typeof
断言MyFunc2
< /strong> 是一个函数以及instanceof
运算符。我们已经知道typeof
检查是否MyFunc2
是否实现了Call
方法。因为MyFunc2
是一个函数并且它实现了call
方法,这就是typeof
知道它是一个函数的方式。另一方面,我们使用函数构造函数
创建MyFunc2
,它成为函数构造函数
的实例code>
。这就是为什么
instanceof
也解析为true
。使用什么更安全?
正如我们在这两种情况下看到的
typeof
运算符可以成功断言我们正在处理这里有一个函数,它比instanceof
更安全。 如果函数声明
,instanceof
将会失败,因为函数声明
< /strong> 不是函数构造函数
的实例。最佳实践:
如Gary Rafferty 建议,最好的方法应该是同时使用 typeof 和 instanceof 。
Of course it matters........ !
Let's walk this through with examples.In our example we will declare function in two different ways.
We will be using both
function declaration
and Function Constructor. We will se howtypeof
andinstanceof
behaves in those two different scenarios.Create function using function declaration :
Possible explanation for such different result is, as we made a function declaration ,
typeof
can understand that it is a function.Becausetypeof
checks whether or not the expression on which typeof is operation on, in our caseMyFunc
implemented Call Method or not. If it implementsCall
method it is a function.Otherwise not .For clarification check ecmascript specification for typeof.Create function using function constructor :
Here
typeof
asserts thatMyFunc2
is a function as well as theinstanceof
operator.We already knowtypeof
check ifMyFunc2
implementedCall
method or not.AsMyFunc2
is a function and it implementscall
method,that's howtypeof
knows that it's a function.On the other hand, we usedfunction constructor
to createMyFunc2
, it becomes an instance ofFunction constructor
.That's whyinstanceof
also resolves totrue
.What's safer to use ?
As we can see in both cases
typeof
operator can successfully asserted that we are dealing with a function here,it is safer thaninstanceof
.instanceof
will fail in case offunction declaration
becausefunction declarations
are not an instance ofFunction constructor
.Best practice :
As Gary Rafferty suggested, the best way should be using both typeof and instanceof together.