What are Reflection and Introspection in JavaScript and Why Do You Need Them?
\n\nImagine you are a programmer-detective. You have an object, but you don't know what's inside it. What properties does it have? What is its nature — an array, a function, or just a set of data? In everyday life, we just look at the code, but in the dynamic world of JavaScript, your program must be able to do this itself. This is reflection and introspection.
\n\nThese terms sound like philosophy, but in reality, they are powerful tools. Introspection is when code looks at itself: it checks the type of a variable, finds out the name of a function, or enumerates the properties of an object. Reflection goes further — it is the ability of code to modify itself during execution: adding new methods, changing prototypes, or even creating proxy objects.
\n\nAt first glance, it might seem that this is only needed by authors of complex frameworks. But in fact, every day you use introspection without even noticing it. When you write typeof x === 'string' — you are already doing introspection. And when you use Object.assign to copy properties — you are applying reflection.
In this article, we will break down all the key methods and techniques. You will learn how to "look inside" any object, how to safely work with unknown data, and how to write more flexible and adaptive code. Let's go!
\n\nBasics of Introspection: Looking at What We Have in Our Hands
\n\nIntrospection starts with a simple question: "What is this?". JavaScript has several built-in operators and methods that help answer this question.
\n\nThe typeof Operator: Quick Type Check
\n\nThis is your first helper. typeof returns a string indicating the type of the operand. It's simple, but it has a couple of pitfalls.
console.log(typeof 42); // "number"\nconsole.log(typeof 'hello'); // "string"\nconsole.log(typeof true); // "boolean"\nconsole.log(typeof undefined); // "undefined"\nconsole.log(typeof null); // "object" — here it is, the famous bug!\nconsole.log(typeof []); // "object" — and this is not a bug, but a feature\nconsole.log(typeof function(){}); // "function"\n\nNote: typeof null returns "object". This is a historical error in JavaScript that won't be fixed. typeof [] also returns "object", which is logical since an array is a subtype of an object. But how then to distinguish an array from a regular object? There are other tools for that.
Useful tip: typeof is perfect for checking if a variable is defined, without the risk of throwing a ReferenceError exception.
if (typeof someGlobalVar !== 'undefined') {\n // Safely use someGlobalVar\n}\n\ninstanceof: Checking the Prototype Chain
\n\nIf typeof answers the question "what primitive type?", then instanceof answers "is it an object of a certain class?". It checks whether the constructor's prototype is present in the object's prototype chain.
const arr = [1, 2, 3];\nconsole.log(arr instanceof Array); // true\nconsole.log(arr instanceof Object); // true — because Array inherits from Object\n\nconst date = new Date();\nconsole.log(date instanceof Date); // true\nconsole.log(date instanceof Object); // true\n\n// But it doesn't work with primitives\nconsole.log('hello' instanceof String); // false — primitive is not an object\n\nImportant nuance: instanceof can fail when working with iframes or different execution contexts (e.g., in Node.js). Each context has its own global object, and [] instanceof window.Array might return false if the array was created in a different frame. For such cases, it's better to use Array.isArray().