Suggest an editImprove this articleRefine the answer for “Difference between in operator and hasOwnProperty() method in JavaScript”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**The `in` operator** checks if a property exists in an object or anywhere in its prototype chain. `hasOwnProperty()` checks only the object's own properties. ```javascript const obj = { a: 1 }; 'a' in obj; // true (own) 'toString' in obj; // true (inherited) obj.hasOwnProperty('a'); // true obj.hasOwnProperty('toString'); // false ``` **Key point:** use `in` for full existence checks, `hasOwnProperty()` when you need to exclude inherited properties.Shown above the full answer for quick recall.Answer (EN)Image**The `in` operator** checks if a property exists anywhere in an object's prototype chain, including inherited ones. `hasOwnProperty()` looks only at the object's own properties and skips the chain entirely. ## Theory ### TL;DR - `in` is like asking "does this house or any ancestor have a garage?" `hasOwnProperty()` asks "does this specific house have one?" - Main difference: `in` walks up the prototype chain, `hasOwnProperty()` stops at the object itself - Both work with non-enumerable own properties. `Object.keys()` is the one that filters by enumerability, not `hasOwnProperty()` - Use `in` for full existence checks or pre-access safety. Use `hasOwnProperty()` to exclude inherited properties ### Quick example ```javascript const parent = { skill: 'coding' }; const child = Object.create(parent); child.name = 'Alice'; console.log('name' in child); // true (own property) console.log('skill' in child); // true (inherited from parent) console.log(child.hasOwnProperty('name')); // true console.log(child.hasOwnProperty('skill')); // false (lives on parent, not child) ``` `in` found both properties. `hasOwnProperty()` returned `false` for `skill` because it belongs to `parent`, not to `child` directly. ### Key difference `in` triggers the `[[HasProperty]]` internal method which walks the `[[Prototype]]` chain upward until it finds a match or hits `null`. `hasOwnProperty()` goes straight to the object's local property map and never looks up the chain. Both methods see non-enumerable own properties. The one that filters by enumerability is `Object.keys()`, not `hasOwnProperty()`. ### When to use - Checking before accessing a prop (safety guard before `obj.prop`): use `in` - Full feature detection, including browser APIs on prototypes: use `in` - Filtering direct keys inside a `for...in` loop: use `hasOwnProperty()` - Serializing only user-defined properties, not defaults inherited from a prototype: use `hasOwnProperty()` - Protecting against prototype pollution in library code: use `hasOwnProperty()` ### Comparison table | Characteristic | `in` | `hasOwnProperty()` | |---|---|---| | Searches prototype chain | Yes | No (own only) | | Non-enumerable own properties | Returns `true` | Returns `true` | | Null-prototype objects (`Object.create(null)`) | Works fine | Throws `TypeError` if called directly | | Performance | Slower (chain traversal) | Faster (local lookup) | | Typical use case | Safe access, feature detection | `for...in` filtering, serialization | ### How JavaScript handles this `in` calls the ECMAScript `[[HasProperty]]` internal method, which follows `[[Prototype]]` links until it finds the key or reaches `null`. `hasOwnProperty()` calls `OrdinaryOwnPropertyKeys` directly on the object's property map. That is why `hasOwnProperty()` runs roughly 2-3x faster in tight loops. ### Common mistakes **Mistake: `for...in` without filtering own properties** ```javascript function User() {} User.prototype.greet = function() {}; const user = new User(); user.name = 'Alice'; for (let key in user) { console.log(key); // 'name', then 'greet' (inherited!) } ``` `for...in` iterates all enumerable properties, including inherited ones. Fix it with `hasOwnProperty()`: ```javascript for (let key in user) { if (user.hasOwnProperty(key)) { console.log(key); // only 'name' } } ``` Or just use `Object.keys(user)`, which returns own enumerable keys directly. **Mistake: calling `hasOwnProperty` on a null-prototype object** ```javascript const config = Object.create(null); // no prototype config.port = 3000; config.hasOwnProperty('port'); // TypeError: config.hasOwnProperty is not a function ``` Objects created with `Object.create(null)` have no prototype, so they do not inherit `hasOwnProperty`. Fix: ```javascript Object.prototype.hasOwnProperty.call(config, 'port'); // true // Or the cleaner modern option: Object.hasOwn(config, 'port'); // true (ES2022) ``` I ran into this in a Node.js config loader where null-prototype objects were used to prevent prototype pollution. `Object.hasOwn` fixed it cleanly. **Mistake: thinking `hasOwnProperty` skips non-enumerable properties** ```javascript const obj = {}; Object.defineProperty(obj, 'hidden', { value: 99, enumerable: false }); console.log('hidden' in obj); // true console.log(obj.hasOwnProperty('hidden')); // true (not false!) console.log(Object.keys(obj)); // [] <- this one skips non-enumerable ``` `hasOwnProperty()` does not care about enumerability. It returns `true` for any own property. `Object.keys()` is the one that requires `enumerable: true`. ### Real-world usage - React: `for...in` + `hasOwnProperty` in `ReactElementValidator` to check propTypes (React 18) - Express: `req.hasOwnProperty('user')` to guard against prototype leaks in middleware - Lodash: `_.has(object, path)` uses `in`-style logic for safe deep property access - Node.js: null-prototype objects in config parsers, paired with `Object.hasOwn` ### Follow-up questions **Q:** What happens when you use `in` on an `Object.create(null)` object? **A:** It works for own properties but finds nothing inherited, since there is no prototype chain. `'toString' in Object.create(null)` returns `false`. **Q:** What is `Object.hasOwn()` and how does it differ from `hasOwnProperty()`? **A:** `Object.hasOwn(obj, key)` was added in ES2022. It does the same thing but works correctly on null-prototype objects. Prefer it in new code. **Q:** How to safely iterate only own keys? **A:** Use `Object.keys(obj)` for own enumerable keys, or `for...in` with a `hasOwnProperty()` filter. `Object.keys` is the cleaner option. **Q:** In a Proxy-trapped object, does `in` respect custom behavior? **A:** Yes. `in` calls the Proxy's `has` trap, so you can intercept the check. `hasOwnProperty()` bypasses the trap and goes directly to the target object. This is defined in the ES2022 spec and matters in metaprogramming contexts. ## Examples ### Checking inherited vs own in a class hierarchy ```javascript function Animal(name) { this.name = name; } Animal.prototype.type = 'animal'; const dog = new Animal('Rex'); console.log('name' in dog); // true (own property) console.log('type' in dog); // true (inherited from Animal.prototype) console.log(dog.hasOwnProperty('name')); // true console.log(dog.hasOwnProperty('type')); // false ``` `type` lives on `Animal.prototype`, not on `dog`. `in` finds it anyway. `hasOwnProperty()` does not. This is the clearest way to see the difference. ### Serializing only user-defined settings ```javascript const defaults = { theme: 'light', lang: 'en' }; const userConfig = Object.create(defaults); userConfig.lang = 'uk'; userConfig.fontSize = 16; // Save only what the user explicitly set const toSave = {}; for (let key in userConfig) { if (userConfig.hasOwnProperty(key)) { toSave[key] = userConfig[key]; } } console.log(toSave); // { lang: 'uk', fontSize: 16 } // 'theme' stays out because it is on defaults, not on userConfig ``` A pattern that comes up in configuration systems. Without the `hasOwnProperty` check, default values the user never touched would end up in the saved output.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.