An API response arrives with a missing field, and the code has to decide what to do. Testing the value is not enough: an absent field and a field holding zero look the same if all you do is look at what it contains.
in answers a different question: is the property there at all, whatever its value.
Definition
in is an operator returning true when the property named on its left exists on the object placed on its right. The property name goes in quotes, because it is a string.
const customer = { name: 'Marie', credits: 0 };
'name' in customer; // true
'credits' in customer; // true
'email' in customer; // falseThe second line is the case that justifies the operator. Writing if (customer.credits) gives false, because zero counts as a value treated as false under the Truthy and falsy rules, even though the property genuinely exists.
What in actually finds
The operator does not stop at an object's own properties: it also walks the inheritance chain, where the methods provided by the language live.
const customer = { name: 'Marie' };
'toString' in customer; // true, inherited
Object.hasOwn(customer, 'toString'); // false
Object.hasOwn(customer, 'name'); // trueThat behavior is rarely a problem, but it becomes dangerous on an object used as a dictionary filled from outside data: 'constructor' in dictionary answers true without anyone having added a thing.
| Question being asked | The right test |
|---|---|
| Does the property exist, inheritance included | 'x' in object |
| Does the object carry it itself | Object.hasOwn(object, 'x') |
| Is the value usable | object.x != null |
On an array, in is about indexes
Since an Array is an object, the operator works there too, but it tests for the presence of an index, never of a value.
const colors = ['red', 'green', 'blue'];
0 in colors; // true
3 in colors; // false
'red' in colors; // false
colors.includes('red'); // trueAfter a delete on an element, the index disappears while the array length stays put: 1 in colors becomes false and the array keeps a hole. That is the clearest demonstration of what the operator really measures.
Frequently asked questions
How is it different from object.x !== undefined?
That comparison fails on a property that exists but explicitly holds undefined: it reports the key as absent when it is there. in separates the two situations, which matters as soon as a field set to undefined carries meaning, a preference that was never filled in for instance.
Can I use it to look for a value in an array?
No, and the confusion is common. in looks at indexes, so 'red' in colors returns false even when the color sits in the array. The includes() method answers that question, and indexOf() additionally gives you the position.
Is it the same word as in a for...in loop?
The word is identical, the construct is not. for (const key in object) walks the property names instead of testing one of them, and to walk values you need an of loop. Two uses of one keyword, worth keeping apart when you reread your code.