Question
What is the correct way to check whether a JavaScript object contains a key? For example, which approach should be used for myObj and the key "key"?
if (myObj["key"] == undefined) {
// ...
}
if (myObj["key"] == null) {
// ...
}
if (myObj["key"]) {
// ...
}
How do these checks differ, and how can I reliably determine whether the object has the property?
Short Answer
You will learn the difference between checking whether a property exists and checking whether its value is truthy. The recommended modern way to test whether an object owns a key is Object.hasOwn(obj, key).
Concept
A JavaScript object stores properties as key–value pairs:
const user = {
name: "Ava",
active: false,
score: 0
};
Checking whether a key exists is different from checking the value stored at that key.
For example, active, score, and a property whose value is undefined may all exist, even though their values are not truthy:
const settings = {
enabled: false,
retries: 0,
label: "",
token: undefined
};
The most reliable modern check for an object's own property is:
Object.hasOwn(settings, "enabled"); // true
Object.hasOwn(settings, "missing"); // false
An own property is a property stored directly on that object. This matters because objects can also inherit properties through their prototype.
The original checks inspect values instead:
myObj["key"] == undefinedis true when the value isundefinedornull.myObj["key"] == nullhas the same behavior because loose equality treatsnullandundefinedas equal.myObj["key"]checks whether the value is truthy, so it fails for valid values such asfalse,0, and"".
Use a key-existence check when you need to know whether the property is present. Use a value check only when the actual value is what matters.
Mental Model
Think of an object as a set of labeled drawers.
- Checking
Object.hasOwn(cabinet, "key")asks: “Does this cabinet have a drawer labeledkey?” - Reading
cabinet["key"]asks: “What is inside that drawer?” - Writing
if (cabinet["key"])asks: “Is what is inside useful/truthy?”
A drawer can exist while holding 0, false, an empty string, or even undefined. Therefore, its contents do not reliably tell you whether the drawer exists.
Syntax and Examples
Use Object.hasOwn() to check for a property stored directly on an object:
Object.hasOwn(object, propertyName);
const product = {
name: "Notebook",
stock: 0,
featured: false
};
console.log(Object.hasOwn(product, "name")); // true
console.log(Object.hasOwn(product, "stock")); // true
console.log(Object.hasOwn(product, "price")); // false
Even though product.stock is 0 and product.featured is false, those keys exist:
console.log(Object.hasOwn(product, "stock")); // true
console.log(Object.hasOwn(product, "featured")); // true
console.log(Boolean(product.stock)); // false
console.log(Boolean(product.featured)); // false
If you specifically need to include inherited properties, use the in operator:
const account = Object.create({ type: "member" });
account.name = "Mina";
console.log("name" in account); // true: own property
console.log("type" in account); // true: inherited property
console.log(Object.hasOwn(account, "type")); // false
For older environments where Object.hasOwn() is unavailable, use:
Object.prototype.hasOwnProperty.call(object, propertyName);
const data = { id: 42 };
const hasId = Object.prototype.hasOwnProperty.call(data, "id");
console.log(hasId); // true
Step by Step Execution
Consider this object:
const preferences = {
darkMode: false,
fontSize: 0,
nickname: "",
timezone: undefined
};
console.log(Object.hasOwn(preferences, "darkMode"));
console.log(Object.hasOwn(preferences, "timezone"));
console.log(Object.hasOwn(preferences, "language"));
console.log(Boolean(preferences.darkMode));
Step by step:
preferencesis created with four keys:darkMode,fontSize,nickname, andtimezone.Object.hasOwn(preferences, "darkMode")returnstruebecausedarkModeis directly stored inpreferences.Object.hasOwn(preferences, "timezone")also returnstrue, even though its value isundefined.Object.hasOwn(preferences, "language")returnsfalsebecause that key was never added.Boolean(preferences.darkMode)returnsfalsebecause the value ofdarkModeisfalse. That does not mean the key is missing.
Output:
true
true
false
false
Real World Use Cases
Property-existence checks are useful whenever an object represents optional input or changing data.
- API responses: Determine whether an API actually sent a field before applying defaults.
- Form updates: Tell the difference between a field omitted from an update and a field intentionally set to
falseor"". - Configuration: Check whether a user supplied a setting, including valid settings such as
0retries. - Feature flags: A flag set to
falseexists and should not be mistaken for a missing flag. - Data validation: Verify required keys before processing JSON-like data.
Example: preserving a deliberate false value in an update:
const update = { emailNotifications: false };
if (Object.hasOwn(update, "emailNotifications")) {
savePreference(update.emailNotifications);
}
A truthiness check would skip this update because false is falsy.
Real Codebase Usage
In production code, developers usually choose the check based on intent.
Validate required fields
function createOrder(payload) {
if (!Object.hasOwn(payload, "productId")) {
throw new Error("productId is required");
}
return { productId: payload.productId };
}
Apply a default only when a key was omitted
function getPageSize(options) {
if (Object.hasOwn(options, "pageSize")) {
return options.pageSize;
}
return 20;
}
getPageSize({ pageSize: 0 }); // 0, not 20
Safely inspect untrusted dictionary-like data
Objects from JSON, user input, or external libraries may not have the usual hasOwnProperty method. Prefer Object.hasOwn() rather than calling a method on the object itself:
function hasPermission(permissions, permission) {
return Object.hasOwn(permissions, permission);
}
Check inherited behavior only when intended
The in operator is sometimes useful for class instances or prototype-based objects, but it is not usually the right choice for validating JSON/API payload fields.
if ("toString" in {}) {
// true, because toString is inherited
}
Common Mistakes
Using truthiness to test key existence
This is incorrect when valid values can be falsy:
const options = { timeout: 0 };
if (options.timeout) {
console.log("Timeout was provided");
}
The message does not run, even though timeout exists. Use:
if (Object.hasOwn(options, "timeout")) {
console.log("Timeout was provided");
}
Comparing with undefined when undefined is a valid value
const record = { middleName: undefined };
console.log(record.middleName === undefined); // true
This cannot distinguish a missing key from an existing key set to undefined:
console.log(Object.hasOwn(record, "middleName")); // true
console.log(Object.hasOwn(record, "lastName")); // false
Assuming == null means “missing”
const data = { note: null };
console.log(data.note == null); // true
This is true for both null and undefined; it does not check key ownership. Use it only when you intentionally want to treat null and undefined as equivalent absent values.
Calling obj.hasOwnProperty() directly
A key can shadow that method, or the object may not inherit from Object.prototype:
const dangerous = {
hasOwnProperty: () => false,
id: 1
};
console.log(dangerous.hasOwnProperty("id")); // false: misleading
Prefer:
console.log(Object.hasOwn(dangerous, "id")); // true
Forgetting that in includes inherited properties
console.log("toString" in {}); // true
console.log(Object.hasOwn({}, "toString")); // false
Use in only if inherited properties should count.
Comparisons
| Check | What it tests | false, 0, "" count as present? | Inherited properties count? |
|---|---|---|---|
Object.hasOwn(obj, "key") | Whether key is an own property | Yes | No |
"key" in obj | Whether key exists anywhere on the object or prototype chain | Yes | Yes |
obj["key"] !== undefined | Whether the value is not undefined | No, if value is undefined | Value lookup can find inherited values |
obj["key"] == null | Whether the value is null or undefined | Not a key-existence check | Value lookup can find inherited values |
if (obj["key"]) | Whether the value is truthy | No | Value lookup can find inherited values |
Use Object.hasOwn() for ordinary object-key validation. Use in when prototype-inherited members are deliberately part of the check. Use truthiness checks only when you truly need a truthy value.
Cheat Sheet
// Recommended: own key exists
Object.hasOwn(obj, "key");
// Include own and inherited keys
"key" in obj;
// Older compatible own-key check
Object.prototype.hasOwnProperty.call(obj, "key");
// Read a value
const value = obj["key"];
Key rules:
Object.hasOwn(obj, "key")istrueeven if the value isfalse,0,"",null, orundefined.if (obj.key)is a truthiness check, not an existence check.obj.key == nullis true fornullandundefined."key" in objincludes inherited properties.- Use bracket notation for dynamic key names:
const key = "email";
Object.hasOwn(user, key);
FAQ
How do I check whether a JavaScript object has a key?
Use Object.hasOwn(object, "key"). It returns true only when the key is directly stored on the object.
Why does if (obj.key) not work for checking a property?
It checks whether the value is truthy. Existing properties with values such as false, 0, "", null, or undefined will not pass the check.
Does Object.hasOwn() work when the value is undefined?
Yes.
Object.hasOwn({ value: undefined }, "value"); // true
What is the difference between Object.hasOwn() and in?
Object.hasOwn() checks direct properties only. The in operator also returns true for properties inherited from an object's prototype.
Should I use obj.hasOwnProperty("key")?
Usually no. It can fail if the object has its own property named hasOwnProperty or does not inherit that method. Prefer Object.hasOwn(obj, "key").
When should I use obj.key == null?
Use it when you intentionally want to treat both null and undefined as “no usable value.” It is not a reliable test for whether a key exists.
Can I check a key stored in a variable?
Yes, use bracket-style arguments:
const key = "status";
Object.hasOwn(response, key);
Mini Project
Description
Build a small profile-update validator. It demonstrates why an existence check is necessary when an update can intentionally set values to false, 0, or an empty string.
Goal
Accept only allowed profile keys and apply every provided update, including falsy values.
Requirements
- Create a profile object with default values.
- Accept an update object containing zero or more fields.
- Allow only
displayName,age, andnewsletterfields. - Apply a field when it exists in the update object, even if its value is falsy.
- Ignore keys that are not allowed.
Keep learning
Related questions
Abort Ajax Requests with jQuery jqXHR.abort()
Learn how to cancel an in-progress jQuery Ajax request with jqXHR.abort(), handle abort status safely, and avoid stale UI updates.
Access the Correct this Inside a JavaScript Callback
Learn why JavaScript this changes in callbacks and how to preserve an object context using bind, arrow functions, and event handler patterns.
Add Key-Value Pairs to JavaScript Objects
Learn how to add key-value pairs to JavaScript objects with dot and bracket notation, dynamic keys, examples, and common mistakes.