What is the difference between typeof and instanceof in JavaScript
As a JavaScript developer, you might often wonder how to correctly identify the type of a variable or determine if an object belongs to a particular class. Two operators that help with this are typeof
and instanceof
. While they may seem similar, they serve different purposes and work in distinct ways. This article will break down these operators, explain their differences, and guide you on when to use each.
Introduction to Data Types in JavaScript
JavaScript is a dynamically typed language, meaning variables can hold values of any type without explicit declarations. Understanding data types is crucial for writing effective code. The primary data types in JavaScript are:
- Primitive Types:
string
,number
,boolean
,undefined
,null
,symbol
, andbigint
. - Objects: Arrays, functions, dates, and user-defined objects.
The typeof
Operator
The typeof
operator is used to determine the type of a variable. It returns a string indicating the type of the operand.
Syntax and Usage
typeof operand
- Operand: The variable or value you want to check.
Examples and Common Pitfalls
Checking Primitive Types
const name = 'Alice'
console.log(typeof name) // 'string'
const age = 25
console.log(typeof age) // 'number'
const isStudent = true
console.log(typeof isStudent) // 'boolean'
const nothing = undefined
console.log(typeof nothing) // 'undefined'
Special Case: null
const empty = null
console.log(typeof empty) // 'object'
Explanation: This is a historical bug in JavaScript. Although null
represents the absence of a value, typeof null
returns 'object'
. Be cautious when checking for null
values.
Functions and Symbols
const greet = function() {}
console.log(typeof greet) // 'function'
const uniqueId = Symbol('id')
console.log(typeof uniqueId) // 'symbol'
Arrays and Objects
const list = []
console.log(typeof list) // 'object'
const person = {}
console.log(typeof person) // 'object'
Note: Both arrays and objects return 'object'
when using typeof
. To differentiate between them, you might need additional checks.
The instanceof
Operator
The instanceof
operator checks if an object is an instance of a specific class or constructor function. It examines the prototype chain to determine this relationship.
Syntax and Usage
object instanceof Constructor
- Object: The object you want to test.
- Constructor: The constructor function or class you want to check against.
Examples and Prototype Chain
Checking Instances
class Person {}
const person = new Person()
console.log(person instanceof Person) // true
console.log(person instanceof Object) // true
Explanation: Since all objects inherit from Object.prototype
, person
is also an instance of Object
.
Arrays and Built-in Objects
const arr = []
console.log(arr instanceof Array) // true
console.log(arr instanceof Object) // true
const date = new Date()
console.log(date instanceof Date) // true
console.log(date instanceof Object) // true
Custom Constructors
function Car(make) {
this.make = make
}
const myCar = new Car('Toyota')
console.log(myCar instanceof Car) // true
console.log(myCar instanceof Object) // true
Key Differences Between typeof
and instanceof
-
Purpose:
typeof
: Determines the primitive type of a variable.instanceof
: Checks if an object is an instance of a specific constructor or class.
-
Return Value:
typeof
: Returns a string (e.g.,'number'
,'string'
).instanceof
: Returns a boolean (true
orfalse
).
-
Scope of Operation:
typeof
: Works on both primitive values and objects but is less informative with objects.instanceof
: Works only with objects and checks the prototype chain.
-
Identifying Arrays and Functions:
typeof []
returns'object'
, while[] instanceof Array
returnstrue
.typeof function() {}
returns'function'
, which is a subtype of'object'
.
When to Use Which Operator
Use typeof
When:
-
Checking Primitive Types: Ideal for variables that hold primitive values.
if (typeof age === 'number') { // Proceed with number-specific logic }
-
Verifying Undefined Variables: Useful to check if a variable is undefined without causing a ReferenceError.
if (typeof undeclaredVariable === 'undefined') { // Variable is not declared or is undefined }
Use instanceof
When:
-
Checking Object Instances: Determine if an object is created from a specific class or constructor.
if (error instanceof TypeError) { // Handle TypeError specifically }
-
Working with Inheritance: Useful in class hierarchies to check if an object inherits from a parent class.
class Animal {} class Dog extends Animal {} const pet = new Dog() console.log(pet instanceof Dog) // true console.log(pet instanceof Animal) // true
Common Mistakes and How to Avoid Them
-
Misinterpreting
typeof null
:-
Issue:
typeof null
returns'object'
, which can be misleading. -
Solution: Check for
null
explicitly.if (value === null) { // Handle null value }
-
-
Assuming
typeof
Identifies Arrays:-
Issue:
typeof []
returns'object'
, not'array'
. -
Solution: Use
Array.isArray()
orinstanceof
.if (Array.isArray(list)) { // Handle array } // Or if (list instanceof Array) { // Handle array }
-
-
Using
instanceof
with Primitives:-
Issue: Primitives are not instances of any class, so
instanceof
returnsfalse
.console.log('hello' instanceof String) // false
-
Solution: Use
typeof
for primitives.
-
-
Cross-Frame Objects:
-
Issue: In browser environments, objects from different frames or windows have different constructors.
// Assuming iframe.contentWindow is a different window context const iframeArray = iframe.contentWindow.arrayFromIframe console.log(iframeArray instanceof Array) // false
-
Solution: Use
Array.isArray()
for reliable array checking.
-
Conclusion
Understanding the differences between typeof
and instanceof
is essential for effective type checking in JavaScript:
- Use
typeof
for simple, primitive types and to check for undefined variables. - Use
instanceof
when dealing with objects, especially to determine inheritance and prototype relationships.
By carefully choosing the appropriate operator and being aware of their quirks and limitations, you can write more robust, maintainable, and error-free code.
Remember: Always test your type checks and be mindful of JavaScript’s special cases to avoid unexpected behavior.