admin管理员组文章数量:1125987
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
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
Share Improve this question edited Nov 28, 2018 at 0:21 naXa stands with Ukraine 37.8k24 gold badges204 silver badges272 bronze badges asked May 22, 2009 at 19:24 farinspacefarinspace 8,7716 gold badges35 silver badges48 bronze badges 4 |27 Answers
Reset to default 716Use instanceof
for custom types:
var ClassFirst = function () {};
var ClassSecond = function () {};
var instance = new ClassFirst();
typeof instance; // object
typeof instance == 'ClassFirst'; // false
instance instanceof Object; // true
instance instanceof ClassFirst; // true
instance instanceof ClassSecond; // false
Use typeof
for simple built in types:
'example string' instanceof String; // false
typeof 'example string' == 'string'; // true
'example string' instanceof Object; // false
typeof 'example string' == 'object'; // false
true instanceof Boolean; // false
typeof true == 'boolean'; // true
99.99 instanceof Number; // false
typeof 99.99 == 'number'; // true
function() {} instanceof Function; // true
typeof function() {} == 'function'; // true
Use instanceof
for complex built in types:
/regularexpression/ instanceof RegExp; // true
typeof /regularexpression/; // object
[] instanceof Array; // true
typeof []; //object
{} instanceof Object; // true
typeof {}; // object
And the last one is a little bit tricky:
typeof null; // object
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.
A good reason to use typeof is if the variable may be undefined.
alert(typeof undefinedVariable); // alerts the string "undefined"
alert(undefinedVariable instanceof Object); // throws an exception
A good reason to use instanceof is if the variable may be null.
var myNullVar = null;
alert(typeof myNullVar ); // alerts the string "object"
alert(myNullVar instanceof Object); // alerts "false"
So really in my opinion it would depend on what type of possible data you are checking.
To make things clear, you need to know two facts:
- The instanceof operator tests whether the prototype property of a constructor appears anywhere in the prototypes chain of an object. In most cases this mean that the object was created by using this constructor or one of its descendant. But also prototype may be set explicitly by
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 return false
, because Array.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.
- The typeof operator tests whether value belong to one of six basic types: "number", "string", "boolean", "object", "function" or "undefined". Where the string "object" belong all objects (except functions, which are objects, but have its own value in typeof operator), and also "null" value and arrays (for "null" it's a bug, but this bug is so old, so it's become a standard). It doesn't rely on constructors and can be used even if value is undefined. But it's doesn't give any details about objects. So if you needed it, go to instanceof.
Now let's talk about one tricky thing. What if you use constructor to create a primitive type?
let num = new Number(5);
console.log(num instanceof Number); // print true
console.log(typeof num); // print object
num++; //num is object right now but still can be handled as number
//and after that:
console.log(num instanceof Number); // print false
console.log(typeof num); // print number
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.
function test(){
console.log(typeof this);
}
test.apply(5);
To avoiding this you can use strict mode:
function test(){
'use strict';
console.log(typeof this);
}
test.apply(5);
upd: Since ECMAScript 2015, there is one more type called Symbol, which has its own typeof == "symbol".
console.log(typeof Symbol());
// expected output: "symbol"
You can read about it on MDN: (Symbol, typeof).
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.
if (typeof this === 'string') {
doStuffWith(this);
}
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 is true
the first time, but false
every time you hit reload!
My brain almost exploded.
So now I've settled on this:
if (this instanceof String || typeof this === 'string')
doStuffWith(this.toString());
}
And now everything works great. Note that you can call "a string".toString()
and it just returns a copy of the string, i.e.
"a string".toString() === new String("a string").toString(); // true
So I'll be using both from now on.
instanceof
also works when callback
is a subtype of Function
, I think
Other Significant practical differences:
// Boolean
var str3 = true ;
alert(str3);
alert(str3 instanceof Boolean); // false: expect true
alert(typeof str3 == "boolean" ); // true
// Number
var str4 = 100 ;
alert(str4);
alert(str4 instanceof Number); // false: expect true
alert(typeof str4 == "number" ); // true
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:
const a = "I'm a string primitive";
const b = new String("I'm a String Object");
typeof a; --> returns 'string'
typeof b; --> returns 'object'
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:
const a = "I'm a string primitive";
const b = new String("I'm a String Object");
a instanceof String; --> returns false
b instanceof String; --> returns true
Reference: https://bambielli.com/til/2017-06-18-typeof-vs-instanceof/
After 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.
TYPES | self | typeof | instanceof | constructor |
---|---|---|---|---|
null | null | object | ||
undefined | undefined | undefined | ||
array [] | Array.isArray([]) | object | Array | |
bool | boolean | Boolean | ||
number | number | Number | ||
string | string | String | ||
symbol | symbol | Symbol | ||
function | function | Function | Function | |
class | function | Function | Function | |
object {} | object | Object | Object | |
RegExp /abc/ | object | RegExp | RegExp | |
new Array() | object | Array | Array | |
new Boolean() | object | Boolean | Boolean | |
new Number() | object | Number | Number | |
new String() | object | String | String | |
new myFunction() | object | myFunction | myFunction | |
new myClass() | object | myClass | myClass |
Thumb Rule:
- For checking primitive types use
typeof
- Null can be checked as
myvar === null
- Undefined can be checked as
myvar === undefined
- Array can be checked using
Array.isArray([])
- Object can be check using
myvar instanceof Object
- Constructor column can be utilized in a similar fashion as
({}).constructor
or([]).constructor
I admit, the guide is not fully correct, as Creating objects or classes in a different way can result in unexpected output. For example, objects or functions created using
Object.create()
method, which are already explained in the thread by most of the clever folks
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:
function isFunction(obj) {
return typeof(obj) == "function";
}
function isArray(obj) {
return typeof(obj) == "object"
&& typeof(obj.length) == "number"
&& isFunction(obj.push);
}
And so on.
When checking for a function, one must always use typeof
.
Here's the difference:
var f = Object.create(Function);
console.log(f instanceof Function); //=> true
console.log(typeof f === 'function'); //=> false
f(); // throws TypeError: f is not a function
This is why one must never use instanceof
to check for a function.
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 than instanceof
:
x instanceof Y
x.constructor === Y
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
or undefined
:
// (null).constructor; // TypeError: null has no properties
// (undefined).constructor; // TypeError: undefined has no properties
(1).constructor; // function Number
''.constructor; // function String
([]).constructor; // function Array
(new Uint8Array(0)).constructor; // function Uint8Array
false.constructor; // function Boolean()
true.constructor; // function Boolean()
(Symbol('foo')).constructor; // function Symbol()
// Symbols work, just remember that this is not an actual constructor:
// new Symbol('foo'); //TypeError: Symbol is not a constructor
Array.prototype === window.frames.Array; // false
Array.constructor === window.frames.Array.constructor; // true
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:
function isTypedArrayConstructor(obj) {
switch (obj && obj.constructor){
case Uint8Array:
case Float32Array:
case Uint16Array:
case Uint32Array:
case Int32Array:
case Float64Array:
case Int8Array:
case Uint8ClampedArray:
case Int16Array:
return true;
default:
return false;
}
}
function isTypedArrayInstanceOf(obj) {
return obj instanceof Uint8Array ||
obj instanceof Float32Array ||
obj instanceof Uint16Array ||
obj instanceof Uint32Array ||
obj instanceof Int32Array ||
obj instanceof Float64Array ||
obj instanceof Int8Array ||
obj instanceof Uint8ClampedArray ||
obj instanceof Int16Array;
}
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:
let s = 0,
n = 0;
function typeofSwitch(t) {
switch (typeof t) {
case "string":
return ++s;
case "number":
return ++n;
default:
return 0;
}
}
// note: no test for null or undefined here
function constructorSwitch(t) {
switch (t.constructor) {
case String:
return ++s;
case Number:
return ++n;
default:
return 0;
}
}
let vals = [];
for (let i = 0; i < 1000000; i++) {
vals.push(Math.random() <= 0.5 ? 0 : 'A');
}
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!
Use instanceof because if you change the name of the class you will get a compiler error.
instanceof
will not work for primitives eg "foo" instanceof String
will return false
whereas typeof "foo" == "string"
will return true
.
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:
function Dog() {}
var obj = new Dog;
typeof obj == 'Dog' // false, typeof obj is actually "object"
obj instanceof Dog // true, what we want in this case
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.
(typeof function(){} == 'function') == (function(){} instanceof Function)
but
(typeof 'foo' == 'string') != ('foo' instanceof String)
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
.
Performance
typeof
is faster than instanceof
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
:
var subject = new Array();
var iterations = 10000000;
var goBenchmark = function(callback, iterations) {
var start = Date.now();
for (i=0; i < iterations; i++) { var foo = callback(); }
var end = Date.now();
var seconds = parseFloat((end-start)/1000).toFixed(2);
console.log(callback.name+" took: "+ seconds +" seconds.");
return seconds;
}
// Testing instanceof
var iot = goBenchmark(function instanceofTest(){
(subject instanceof Array);
}, iterations);
// Testing typeof
var tot = goBenchmark(function typeofTest(){
(typeof subject == "object");
}, iterations);
var r = new Array(iot,tot).sort();
console.log("Performance ratio is: "+ parseFloat(r[1]/r[0]).toFixed(3));
Result
instanceofTest took: 9.98 seconds.
typeofTest took: 8.33 seconds.
Performance ratio is: 1.198
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. Using a === null
to check null instead.
on the other hand, function
is also a special case, which is built-in object but typeof
return function
as you can see instanceof
must go through the prototype chain meanwhile typeof
just check the root type one time so it's easy to understand why typeof
is faster than instanceof
Significant practical difference:
var str = 'hello word';
str instanceof String // false
typeof str === 'string' // true
Don't ask me why.
var newObj = new Object;//instance of Object
var newProp = "I'm xgqfrms!" //define property
var newFunc = function(name){//define function
var hello ="hello, "+ name +"!";
return hello;
}
newObj.info = newProp;// add property
newObj.func = newFunc;// add function
console.log(newObj.info);// call function
// I'm xgqfrms!
console.log(newObj.func("ET"));// call function
// hello, ET!
console.log(newObj instanceof Object);
//true
console.log(typeof(newObj));
//"object"
According to MDN documentation about typeof, objects instantiated with the "new" keyword are of type 'object':
typeof 'bla' === 'string';
// The following are confusing, dangerous, and wasteful. Avoid them.
typeof new Boolean(true) === 'object';
typeof new Number(1) === 'object';
typeof new String('abc') === 'object';
While documentation about instanceof points that:
const objectString = new String('String created with constructor');
objectString instanceOf String; // returns true
objectString instanceOf Object; // returns true
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
.
/**
* Did you ever heard of Anakandavada, the doctrine of manifoldness of reality?
* 1) Check: typeof value === 'object'
* 2) Check: value instanceof Object
* 3) Check (1) *and* (2)
* 4) neither
* You may ponder to either use (1) or (2), but only (3) is right, because:
* 1) Fails for functions, every function is also an object: Math.sqrt.test = "Hai"
* 2) Fails for prototype-less objects: Object.create(null) instanceof Object === false.
* @param {*} value - The actual value that we need to validate.
* @returns {boolean} Boolean indicating if value is an object.
*/
function isObject(value) {
return value instanceof Object || typeof value === 'object';
}
To be very precise instanceof should be used where value is created via the constructor (generally custom types) for e.g.
var d = new String("abc")
whereas typeof to check values created just by assignments for e.g
var d = "abc"
Coming from a strict OO upbringing I'd go for
callback instanceof Function
Strings are prone to either my awful spelling or other typos. Plus I feel it reads better.
Despite instanceof may be a little bit faster then typeof, I prefer second one because of such a possible magic:
function Class() {};
Class.prototype = Function;
var funcWannaBe = new Class;
console.log(funcWannaBe instanceof Function); //true
console.log(typeof funcWannaBe === "function"); //false
funcWannaBe(); //Uncaught TypeError: funcWannaBe is not a function
One more case is that You only can collate with instanceof
- it returns true or false. With typeof
you can get type of provided something
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
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 how typeof
and instanceof
behaves in those two different scenarios.
Create function using function declaration :
function MyFunc(){ }
typeof Myfunc == 'function' // true
MyFunc instanceof Function // false
Possible explanation for such different result is, as we made a function declaration , typeof
can understand that it is a function.Because typeof
checks whether or not the expression on which typeof is operation on, in our case MyFunc
implemented Call Method or not. If it implements Call
method it is a function.Otherwise not .For clarification check ecmascript specification for typeof.
Create function using function constructor :
var MyFunc2 = new Function('a','b','return a+b') // A function constructor is used
typeof MyFunc2 == 'function' // true
MyFunc2 instanceof Function // true
Here typeof
asserts that MyFunc2
is a function as well as the instanceof
operator.We already know typeof
check if MyFunc2
implemented Call
method or not.As MyFunc2
is a function and it implements call
method,that's how typeof
knows that it's a function.On the other hand, we used function constructor
to create MyFunc2
, it becomes an instance of Function constructor
.That's why instanceof
also resolves to true
.
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 than instanceof
. instanceof
will fail in case of function declaration
because function declarations
are not an instance of Function constructor
.
Best practice :
As Gary Rafferty suggested, the best way should be using both typeof and instanceof together.
function isFunction(functionItem) {
return typeof(functionItem) == 'function' || functionItem instanceof Function;
}
isFunction(MyFunc) // invoke it by passing our test function as parameter
本文标签:
版权声明:本文标题:javascript - What is the difference between typeof and instanceof and when should one be used vs. the other? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736676078a1947187.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
Object.prototype.toString
ecma-international.org/ecma-262/6.0/… – rab Commented Jun 28, 2015 at 15:04.constructor
property instead. – Muhammad Umer Commented Aug 2, 2015 at 17:16