Detailed explanation
In JavaScript, typeof and instanceof answer different questions. typeof asks, “What broad type of value is this?” and returns a string. instanceof asks, “Does this object inherit from a particular constructor’s prototype?” and returns a boolean. This distinction matters because JavaScript has primitive values as well as objects, and a general type label does not reveal an object’s inheritance relationship. Interviewers expect you to explain both the return values and when each operator is useful.
typeof produces labels such as 'undefined', 'boolean', 'number', 'bigint', 'string', 'symbol', 'function', and 'object'. For example, typeof 42 is 'number', typeof 'hello' is 'string', and typeof (() => {}) is 'function'. Arrays and ordinary objects both produce 'object'. Importantly, typeof null also produces 'object' because of a historical language quirk; null is still a primitive value. Therefore, check null using value === null. typeof can also check an undeclared identifier without throwing, although accessing a let or const binding before its initialisation still throws a ReferenceError.
For ordinary constructors, instanceof works by taking the constructor’s prototype property and searching for that exact object along the left-hand object’s prototype chain. For example, [] instanceof Array is true because Array.prototype appears in the array’s chain. [] instanceof Object is also true because Object.prototype appears further along that chain. With class Student {}, new Student() instanceof Student is true. This checks the current prototype relationship, not a permanent record of which constructor created the value. Constructors can also customise instanceof behaviour through Symbol.hasInstance, though that is usually an advanced follow-up.
Use typeof for primitive type checks and basic callable checks, and instanceof when an inheritance relationship matters within a known environment. Primitive strings fail instanceof String, while wrapper objects created with new String('hello') pass it. Objects from another realm, such as an iframe, may fail instanceof checks against your realm’s constructors because their prototypes differ. For arrays, prefer Array.isArray(value): it recognises genuine arrays across realms and avoids the ambiguity of typeof.
Key points to remember
- typeof returns a type-label string; instanceof returns a boolean.
- typeof [] and typeof null both return 'object', but null is a primitive.
- Ordinary instanceof checks whether a constructor’s prototype occurs in an object’s prototype chain.
- Primitive values generally fail instanceof checks against their corresponding wrapper constructors.
- Use Array.isArray(value) for arrays, including arrays originating in another realm.
Common mistakes candidates make
- Assuming typeof distinguishes arrays, null, and ordinary objects.
- Treating instanceof as proof of the original constructor rather than a prototype-chain check.
- Relying on value instanceof Array for arrays received from an iframe or another realm.
Likely follow-up questions
How do you check whether a value is a non-null object?
Use value !== null && typeof value === 'object'. This includes arrays and dates but excludes functions, so refine the check if your requirement is specifically a plain object.
Why is 'hello' instanceof String false?
'hello' is a primitive string, not an object with String.prototype in its prototype chain. new String('hello') creates a wrapper object, so it passes instanceof String, but primitive strings are normally preferred.
Can an object pass instanceof without being created by that constructor?
Yes: const item = Object.create(Array.prototype) makes item instanceof Array true because Array.prototype is in its prototype chain. However, Array.isArray(item) is false because inheriting from Array.prototype does not make an object a genuine array.
Interview tip: Start with the different return types, demonstrate both operators on an array, and finish with the null caveat and Array.isArray recommendation.
