Which is best to use: typeof or instanceof?
Which is best to use: typeof or 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
There is another way to check type using
Object.prototype.toString
ecma-international.org/ecma-262/6.0/…– rab
Jun 28 '15 at 15:04
Object.prototype.toString
just use
.constructor
property instead.– Muhammad Umer
Aug 2 '15 at 17:16
.constructor
If you wonder about performance, see my answer below. typeof is faster where both are applicable (namely objects).
– Martin Peter
Aug 28 '15 at 13:29
21 Answers
21
instanceof
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
typeof
'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
instanceof
/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
This answer makes it clear why instaceof should not be used for primitive types. It's pretty obvious you don't have an option when it comes to custom types, as well as the benefit for 'object' types. But what makes functions lumped in with "simple built-in types"? I find it odd how a function behaves like an object, yet it's type is 'function' making the use of 'typeof' feasible. Why would you discourage instanceof for it, though?
– Assimilater
Jul 29 '14 at 2:06
@Assimilater you could use instanceof with functions as well however I consider these 3 rules being very simple to remember and yes, functions are an exception:)
– Szymon Wygnański
May 3 '15 at 5:19
another tricky part -> 'example string' instanceof String; // false but new String('example string') instanceof String; //true
– Luke
Nov 13 '15 at 8:57
@Luke generally a bad idea to use "new String" like this. that creates a "string object" rather than a string primitive. see section here developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
– Colin D
Jan 29 '16 at 9:43
Use instanceof for complex built in types
- this is still prone to error. Better to use ES5 Array.isArray()
et al. or the recommended shims.– OrangeDog
May 4 '16 at 11:27
Use instanceof for complex built in types
Array.isArray()
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.
instanceof
there are some situations where instanceof will not work as expected and typeof works well ... developer.mozilla.org/En/Core_JavaScript_1.5_Reference/…
– farinspace
May 22 '09 at 19:37
instanceof works with objects in the same window. If you use iframe/frame or popup-windows each (i)frame/window have their own "function" object and instanceof will fail if you try to compare an object from another (i)frame/window. typeof will work in all cases since it returns the string "function".
– some
May 23 '09 at 16:56
jsperf.com/typeof-function-vs-instanceof/3 I tried on Chrome and FF3.X, "typeof" approach is faster.
– Morgan Cheng
Jun 14 '11 at 3:03
This is just false. They are not identical. They do not both work in all of the same situations, especially across different JavaScript VMs and browsers.
– Justin Force
Nov 22 '11 at 0:48
Your answer says "both are essentially identical in terms of functionality." Respectfully, this is patently false. As outlined and explained in my answer, neither option works in every situation—especially across browsers. The better approach is to use both with an || operator.
– Justin Force
Nov 29 '11 at 20:27
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.
+1 also note that
instanceof
cannot compare to primitive types, typeof can.– Tino
Mar 18 '11 at 11:42
instanceof
In Chrome 29.0.1541.0 dev
undefined instanceof Object
returns false, and doesn't throw an exception. I don't know how recent that change is, but it makes instanceof
more appealing.– Cypress Frankenfeld
Jun 26 '13 at 16:01
undefined instanceof Object
instanceof
undefined instanceof Object
doesn't throw an exception because, eh, undefined
is defined. The constant exists in the namespace. When a variable does not exist (due to typo for instance), instanceof will throw an exception. Using typeof on an non-existing variable yields 'undefined' on the other hand.– cleong
Mar 28 '15 at 13:06
undefined instanceof Object
undefined
To make things clear, you need to know two facts:
This means that instanceof is applicable only to objects.
This is the reason why it not used to check primitive types. In most cases you aren't using constructors to create strings or numbers. You can. But almost never do.
Also it 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.
instanceof window.frames[0].Array
false
Array.prototype !== window.frames[0].Array
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).
if an object is created by a given constructor
This is incorrect. o instanceof C
will return true if o inherits from C.prototype. You have mentioned something about this later in your answer but it is not very clear.– oyenamit
Mar 13 at 19:46
if an object is created by a given constructor
o instanceof C
incorrect...from the book : " github.com/getify/You-Dont-Know-JS" a instanceof Foo; // true The instanceof operator takes a plain object as its left-hand operand and a function as its right-hand operand. The question instanceof answers is: in the entire [[Prototype]] chain of a, does the object arbitrarily pointed to by Foo.prototype ever appear?
– Deen John
Apr 25 at 11:36
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!
false
true
false
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()
"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
instanceof
callback
Function
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
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.
instanceof
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.
In case you didn't know: typeof don't need parenthesis since it is a keyword and not a function. And IMHO you should use === instead of ==.
– some
May 23 '09 at 17:05
@some You are right about typeof but in this case there is no need for ===, it is only needed when the value being compared could equal without having the same type. Here, it can't.
– Nicole
Mar 4 '10 at 19:08
@some does typeof ever return something other than a string?
– Kenneth J
May 21 '10 at 16:15
So isArray would be wrong for, say, a stack object with a push method and a numeric length attribute. Under what circumstances would (instanceof Array) be wrong?
– Chris Noe
Nov 8 '10 at 23:43
@ChrisNoe The problem arises with objects shared between multiple frames: groups.google.com/forum/#!msg/comp.lang.javascript/XTWYCOwC96I/…
– Davy Wybiral
Dec 8 '13 at 20:11
instanceof
will not work for primitives eg "foo" instanceof String
will return false
whereas typeof "foo" == "string"
will return true
.
instanceof
"foo" instanceof String
false
typeof "foo" == "string"
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:
typeof
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()
.
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
.
instanceOf
window.Function
When checking for a function, one must always use typeof
.
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.
instanceof
I can argue that it is
typeof
that is wrong -- f
is all of the following: an Object
(an object) and a Function
(a function). Except for me it makes more sense to use instanceof
because knowing that it is a function I know it is an object as well, since all functions are objects in ECMAScript. The converse is not true -- knowing from typeof
that f
is indeed an object
I have no idea that it is also a function.– amn
May 28 at 12:39
typeof
f
Object
Function
instanceof
typeof
f
object
Significant practical difference:
var str = 'hello word';
str instanceof String // false
typeof str === 'string' // true
Don't ask me why.
Because here
str
is a string primitive, not a string object. The same goes for number primitives and boolean primitives, they aren't instances of their "constructed" counterparts, the String, Number and Boolean objects. JavaScript automatically converts these three primitives to objects when required (such as utilizing a method on the object's prototype chain). On the flip side of your practical difference, instanceof is better for checking for arrays since typeof == "object" // true
.– Andy E
Oct 3 '10 at 19:20
str
typeof == "object" // true
Performance
typeof
is faster than instanceof
in situations where both are applicable.
typeof
instanceof
Depending on your engine, the performance difference in favor of typeof
could be around 20%. (Your mileage may vary)
typeof
Here is a benchmark testing for Array
:
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
typeof subject == "array" should return false. typeof subject is "object".
– Shardul
Feb 5 '17 at 1:43
Right, thanks. Corrected it ..
– Martin Peter
Feb 13 '17 at 9:16
how come typeof is faster? is Javascript interning the literal strings?
– Gregory Magarshak
Apr 30 '17 at 18:25
The reason is:
instanceof
always follows object's prototype chain, so performance penalty will depend on how far in prototype chain is the class, instanceof
is tested against. So for short inheritance chain the penalty will be lower (like, instanceof Array
, {} instanceof Object
), and for long - bigger. So, if both obj instanceof SomeClass
and typeof obj !== 'string'
means the same from the perspective of some your hypothetical code (f.e. if you just making a test in if
, and not switch
-ing through multiple classes etc.), then you'd better pick second one, performance-wise,– ankhzet
Jun 13 '17 at 8:37
instanceof
instanceof
instanceof Array
{} instanceof Object
obj instanceof SomeClass
typeof obj !== 'string'
if
switch
This is just complementary knowledge to all the other explanations here - I am not suggesting to use .constructor
everywhere.
.constructor
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
:
typeof
Object.prototype.constructor
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
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:
instanceof
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:
typeof
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.
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"
What should I do, can I get UA(navigator.userAgent)?
– xgqfrms
Sep 7 '16 at 12:16
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
instanceof
typeof
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.
function declaration
typeof
instanceof
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.
typeof
typeof
MyFunc
Call
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
.
typeof
MyFunc2
instanceof
typeof
MyFunc2
Call
MyFunc2
call
typeof
function constructor
MyFunc2
Function constructor
instanceof
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
.
typeof
instanceof
instanceof
function declaration
function declarations
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
any constructive criticism regarding this answer will be appreciated.
– AL-zami
Jan 4 at 9:49
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
I found my answer here as a easy to use solution
– CrandellWS
Apr 26 '14 at 22:26