5

I was wondering which one of typeof and instanceof is more performant, so I threw together the following little thing:

let TIMES = 1000 * 1000 * 100

console.time("(() => { }) instanceof Function")
for (let i = 0; i < TIMES; i++)
  (() => { }) instanceof Function
console.timeEnd("(() => { }) instanceof Function")

console.time("(async () => { }) instanceof Function")
for (let i = 0; i < TIMES; i++)
  (async () => { }) instanceof Function
console.timeEnd("(async () => { }) instanceof Function")

console.time("(function () { }) instanceof Function")
for (let i = 0; i < TIMES; i++)
  (function () { }) instanceof Function
console.timeEnd("(function () { }) instanceof Function")

console.time("(async function () { }) instanceof Function")
for (let i = 0; i < TIMES; i++)
  (async function () { }) instanceof Function
console.timeEnd("(async function () { }) instanceof Function")

console.time("typeof (() => { }) === 'function'")
for (let i = 0; i < TIMES; i++)
  typeof (() => { }) === 'function'
console.timeEnd("typeof (() => { }) === 'function'")

console.time("typeof (async () => { }) === 'function'")
for (let i = 0; i < TIMES; i++)
  typeof (async () => { }) === 'function'
console.timeEnd("typeof (async () => { }) === 'function'")

console.time("typeof (function () { }) === 'function'")
for (let i = 0; i < TIMES; i++)
  typeof (function () { }) === 'function'
console.timeEnd("typeof (function () { }) === 'function'")

console.time("typeof (async function () { }) === 'function'")
for (let i = 0; i < TIMES; i++)
  typeof (async function () { }) === 'function'
console.timeEnd("typeof (async function () { }) === 'function'")

And got these super cool results from Chrome 66's console:

(() => { }) instanceof Function: 1789.844970703125ms
(async () => { }) instanceof Function: 2229.64208984375ms
(function () { }) instanceof Function: 1954.09716796875ms
(async function () { }) instanceof Function: 2279.995849609375ms
typeof (() => { }) === 'function': 412.8701171875ms
typeof (async () => { }) === 'function': 413.337890625ms
typeof (function () { }) === 'function': 413.387939453125ms
typeof (async function () { }) === 'function': 412.910888671875ms

Firefox 59 took forever to run that XD

I didn't have enough patience to wait for it and made TIMES ten times less:

let TIMES = 1000 * 1000 * 10

With that I got the following out of Firefox 59's console:

(() => { }) instanceof Function: 5490ms
(async () => { }) instanceof Function: 6884ms
(function () { }) instanceof Function: 5408ms
(async function () { }) instanceof Function: 6938ms
typeof (() => { }) === 'function': 1916ms
typeof (async () => { }) === 'function': 1998ms
typeof (function () { }) === 'function': 1976ms
typeof (async function () { }) === 'function': 1972ms

Both result sets show that typeof is much faster than instanceof, the fact a couple of other people also mentioned in Which is best to use: typeof or instanceof?.

My question is "y tho"?

Valentine Stone
  • 1,075
  • 8
  • 7
  • 4
    But both are not interchangeable. The usecases of both the operators vary in certain cases. See [this post](https://stackoverflow.com/questions/899574/which-is-best-to-use-typeof-or-instanceof). – 31piy May 03 '18 at 14:33
  • 1
    `typeof` checks only the type (one simple check), `instanceof` check also if it belongs to a super class (multiple checks) – Naramsim May 03 '18 at 14:35
  • 1
    My guess is because variables in the VM have a type token associated with them by default, which is quicker to check than pointer-chasing up to the prototype chain. – Máté Safranka May 03 '18 at 14:35
  • 3
    [The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming.](https://en.wikiquote.org/wiki/Donald_Knuth) – Liam May 03 '18 at 14:47

1 Answers1

1

As you also predicted and showed other links from SO, typeof will be faster (jsperf : https://jsperf.com/instanceof-vs-typeof/5), and this makes sense because typeof will return one of the built in types (Object, undefined and the primitives) while you get to control the right side of the instanceof operand. This means that the instanceof operator should check the prototype chain and see if the right side has been used as a constructor somewhere along. This is naturally more work.

ibrahim tanyalcin
  • 5,643
  • 3
  • 16
  • 22
  • 1
    In this case `(() => {}).__proto__` is directly `Function.prototype` so this is "just one check" – Jonas Wilms May 03 '18 at 14:47
  • For an arrow function yes. Considering __proto__ is akin to `Object.getPrototypeOf`, seems like still, typeof is faster behind the scenes and whatever is done, cheaper than object property access. – ibrahim tanyalcin May 03 '18 at 14:56
  • 1
    This is just the general reminder about using one liner performance tests without paying a great deal of attention to details (optimizations being the dominant factor, cpu clock accuracy, ...) - [nice performance](https://i.imgur.com/i3Dh1u1.png). This is the reason why i downvote 95%+ of "performance tests" on stackoverflow that blindly draw conclusions from botched tests. I am not saying the result is wrong, just the weird jsperf tests should not be the fundament of the argumentation. – ASDFGerte May 03 '18 at 15:18
  • No it should not, I agree with it. There is tons of bottlenecks to optimize till it comes down to a versus between unpolyfillable in-built specs. I do not also think this can be compared fairly because the two operands are not the same at all. – ibrahim tanyalcin May 03 '18 at 16:04