The in operator
The in operator in JavaScript checks whether a given property exists in an object or an index exists in an array. It is one of the basic operators that is often misunderstood: it looks at the presence of a key, not at its value, and it takes the whole prototype chain into account.
Theory
TL;DR
- Syntax:
propName in object, the result is alwaystrueorfalse. - It checks that a key exists, not its value:
'a' in { a: undefined }istrue. - It works with objects, arrays and functions; array indexes are ordinary keys.
- It respects the prototype chain:
'toString' in {}istrue. - For own properties only use
Object.hasOwn(obj, key)orobj.hasOwnProperty(key). - If the right side is not an object (
null,undefined, a number, a string), you get aTypeError.
Quick example
const user = { name: 'Alice', age: 25 };
console.log('name' in user); // true
console.log('email' in user); // false
console.log('toString' in user); // true (inherited)
console.log(Object.hasOwn(user, 'toString')); // false (not an own property)Syntax
propName in objectWhere:
propNameis a string (or an expression that is converted to a string or a symbol),objectis an object, an array or another structure with keys.
A number on the left is allowed too: it is converted to a string, so 0 in arr really checks the key '0'.
Working with objects
const user = {
name: 'Alice',
age: 25
};
console.log('name' in user); // true
console.log('age' in user); // true
console.log('email' in user); // falseThe
inoperator returnstruewhen the property exists in the object, even if its value isundefined.
That is exactly the main subtlety:
const obj = { a: undefined };
console.log('a' in obj); // true
console.log(obj.a === undefined); // trueSo
inchecks that a key is present, not what it holds. The comparisonobj.a === undefinedcannot tell "no such key" from "the key exists but holds undefined", whileincan.
Working with arrays
const arr = ['a', 'b', 'c'];
console.log(0 in arr); // true, index 0 exists
console.log(2 in arr); // true, index 2 exists
console.log(3 in arr); // false, no such indexJavaScript treats array indexes as ordinary properties:
arr[0]is equivalent toarr['0'].
Because of this, in sees holes in sparse arrays: in ['a', , 'c'] the expression 1 in arr is false, although arr.length is 3.
Inheritance through the prototype
The in operator checks not only own properties but also the ones inherited through the prototype chain.
const person = { name: 'Alice' };
console.log('toString' in person); // true, because it is inherited from Object.prototypeTo check own properties only, use
Object.hasOwn(person, 'key')or the olderperson.hasOwnProperty('key'):javascriptperson.hasOwnProperty('toString'); // false person.hasOwnProperty('name'); // true
The same holds for classes:
class User {
constructor() {
this.name = 'Alex';
}
}
User.prototype.age = 25;
const u = new User();
console.log('name' in u); // true (own property)
console.log('age' in u); // true (inherited from the prototype)Error when the right side is not an object
If the right-hand side is not an object and cannot be converted to one, JavaScript throws:
'length' in null; // TypeError
'length' in undefined; // TypeError
'length' in 'text'; // TypeError (a primitive, not an object)So make sure the variable is neither
nullnorundefinedbefore the check, for example withobj && 'key' in obj.
Summary
| Question | Answer |
|---|---|
| What it checks | Presence of a key (property or index) |
| What it works with | Objects, arrays, functions |
| What it returns | true / false |
| Does it respect the prototype | Yes |
| Does it check the value | No |
Examples for comparison:
| Check | Result | Explanation |
|---|---|---|
'name' in { name: 'Alice' } | true | the key exists |
'email' in { name: 'Alice' } | false | there is no such key |
0 in ['a', 'b'] | true | index 0 exists |
2 in ['a', 'b'] | false | index 2 is missing |
'toString' in {} | true | inherited from Object.prototype |
Common mistakes
- Expecting
into check the value. A key whose value isundefinedornullstill returnstrue. - Forgetting the prototype:
'constructor' in objand'toString' in objare alwaystruefor a plain object. - Using
into look for an element in an array.'b' in ['a','b']isfalse, because indexes are checked; for values you needarr.includes('b'). - Calling
inonnullorundefinedand getting aTypeErrorinstead offalse. - Confusing
inwithfor...inand withinstanceof: they are different constructs despite the similar names. - Calling
obj.hasOwnProperty(key)on an object created withObject.create(null); such an object has no such method, soObject.hasOwn(obj, key)is safer.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.