By Rahul — Google Frontend Engineer
typeof — Checking Primitive Types
typeof returns a string indicating the type of the operand. It works on the value itself, not the prototype chain.
typeof 42 // "number"
typeof "hello" // "string"
typeof true // "boolean"
typeof undefined // "undefined"
typeof Symbol() // "symbol"
typeof BigInt(42) // "bigint"
typeof null // "object" ← THE BUG
typeof {} // "object"
typeof [] // "object"
typeof function(){} // "function"The null Bug
typeof null === "object" is a bug from the first version of JavaScript (1995). It was never fixed because too much existing code depends on it. Always check for null explicitly:
// GOOD
if (value !== null && typeof value === 'object') {
// It is actually an object
}instanceof — Checking the Prototype Chain
instanceof checks whether the prototype of a constructor appears anywhere in the prototype chain of an object.
class Animal {}
class Dog extends Animal {}
const dog = new Dog();
dog instanceof Dog // true
dog instanceof Animal // true — checks up the chain
dog instanceof Object // true — everything extends Object
// How it works internally:
// dog.__proto__ === Dog.prototype? Yes → true
// dog.__proto__.__proto__ === Animal.prototype? Yes → trueWhen Each Fails
typeof Cannot Distinguish Objects
typeof [] // "object" — not helpful
typeof {} // "object"
typeof null // "object"
typeof /re/ // "object"
typeof new Date() // "object"
// Use Array.isArray() for arrays
Array.isArray([]) // trueinstanceof Fails Across Realms
// iframe has its own global scope with its own Array constructor
const iframeArray = iframe.contentWindow.eval('[]');
iframeArray instanceof Array // false! Different Array constructor
// This is why Array.isArray() exists — it works across realms
Array.isArray(iframeArray) // trueReal Production Issues
- Cross-iframe instanceof: We had a component library that checked
error instanceof Error. Errors thrown from an iframe failed this check. We switched to duck-typing:error && typeof error.message === 'string' - Bundler duplicates: If two versions of a library are bundled,
instanceoffails because there are two different constructor functions
The Better Approach: Object.prototype.toString
Object.prototype.toString.call([]) // "[object Array]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(/re/) // "[object RegExp]"
Object.prototype.toString.call(new Date) // "[object Date]"This works across realms and gives precise type information.
Best Practices
- Use
typeoffor primitives (string, number, boolean, undefined) - Use
Array.isArray()for arrays - Use
instanceofonly when you control both the constructor and the usage context - For libraries, prefer duck-typing over instanceof
Summary
typeof checks the value type but has the null bug and cannot distinguish objects. instanceof walks the prototype chain but breaks across iframes and bundler duplicates. Use the right tool for the right situation.