DEV Community

Alex M
Alex M

Posted on • Edited on

How to Check if an Object Has a Property in JavaScript

In JavaScript, there are different ways to check if an object has a specific property. The main differences between these approaches, besides performance and syntax, are the access to own prototypes or inherited properties from the prototype chain.

Any value in javaScript, with the exception with undefined and null has a prototype chain, since primitive values are not "by definition" an object, javaScript coerces or boxes the primitive value in a corresponding object. So the values has properties, methods, constructor and prototype inherited from the prototype chain.

prototype chain of string

Some of the next strategies involve checking both the properties directly belonging to the object (own properties) and those inherited from prototypes.

Using in Operator

The in operator returns true if the object contains the property with specified name. Checking in own prototypes or its prototype chain (inherited properties)

code

const user = { name: 'Alex', age: undefined }
const hasName = 'name' in user
const hasSurname = 'surname' in user
const hasAge = 'age' in user
Enter fullscreen mode Exit fullscreen mode

test

test('user should have name property', () => {
 expect(hasName).toBeTruthy()
})

test('user should not have surname property', () => {
 expect(hasSurname).toBeFalsy()
})

test('user should have age property', () => {
 expect(hasAge).toBeTruthy()
})

test('user should have inherited properties', () => {
 expect('valueOf' in user).toBeTruthy()
})
Enter fullscreen mode Exit fullscreen mode

✅ PASS user should have name property
✅ PASS user should NOT have surname property
✅ PASS user should have age property
✅ PASS user should have inherited properties

NOTE: In operator checks the property and not the value assigned, for this reason returns true for age property even when is undefined.

🧐 Comparing with undefined

A quick way to check if the object has a property is to check if the property is defined. However, since a property could have undefined as its value, it is not a reliable way to check.

Despite this disadvantage, this approach has the advantage of having the flexibility to search for properties within nested objects without throwing errors, making use of the optional chaining operator ?..

code

const user = {
  name: 'Alex',
  age: undefined,
  contact: { phone: '+123' }
}
const hasName = user.name !== undefined
const hasSurname = user.surname !== undefined
const hasAge = user.age !== undefined
const hasPhone = user.contact?.phone !== undefined
const hasAddress = user.contact?.address !== undefined
Enter fullscreen mode Exit fullscreen mode

test

test('user should have name property', () => {
 expect(hasName).toBeTruthy()
})

test('user should not have surname property', () => {
 expect(hasSurname).toBeFalsy()
})

test('user should have age property', () => {
 expect(hasAge).toBeTruthy()
})

test('user should have phone property', () => {
 expect(hasPhone).toBeTruthy()
})

test('user should not have address property', () => {
 expect(hasAddress).toBeFalsy()
})

test('user should have inherited properties', () => {
 expect(user.valueOf !== undefined).toBeTruthy()
})
Enter fullscreen mode Exit fullscreen mode

✅ PASS user should have name property
✅ PASS user should NOT have surname property
❌ FAIL user should have age property
✅ PASS user should have phone property
✅ PASS user should NOT have address property
✅ PASS user should have inherited properties

Using Object.hasOwn(object1, 'prop') method

The Object.hasOwn() static method returns true if the specified object has the indicated property as its own property. If the property is inherited, or does not exist, the method returns false.

code

const user = { name: 'Alex', age: undefined }
const hasName = Object.hasOwn(user, 'name')
const hasSurname = Object.hasOwn(user, 'surname')
const hasAge = Object.hasOwn(user, 'age')
Enter fullscreen mode Exit fullscreen mode

test

test('user should have name property', () => {
 expect(hasName).toBeTruthy()
})

test('user should not have surname property', () => {
 expect(hasSurname).toBeFalsy()
})

test('user should have age property', () => {
 expect(hasAge).toBeTruthy()
})

test('user should not have inherited properties', () => {
 expect(Object.hasOwn(user, 'valueOf')).toBeFalsy()
})
Enter fullscreen mode Exit fullscreen mode

✅ PASS user should have name property
✅ PASS user should NOT have surname property
✅ PASS user should have age property
✅ PASS user should NOT have inherited properties

NOTE: Even by overwriting the hasOwn method, the behavior is not affected.

🧐 Using .hasOwnProperty() method

Object.hasOwn() is intended as a replacement for this method.

Despite the hasOwnProperty() method having better browser support, there are two important observations about the behavior:

  1. hasOwnProperty() doesn't work for null-prototype objects, objects created like const user = Object.create(null)

  2. It doesn't work with objects that have overridden the inherited hasOwnProperty() method.
    For this second scenario there a workaround using the hasOwnProperty property from the Object prototype
    Object.prototype.hasOwnProperty.call(myObj, 'myProp') instead of myObj.hasOwnProperty('myProp')

code

// null-prototype objects
const user = Object.create(null)
user.name = 'Alex'
user.surname = 'Smith'
const hasName = user.hasOwnProperty('name')
const hasSurname = Object.prototype.hasOwnProperty.call(user, 'surname')
Enter fullscreen mode Exit fullscreen mode

test

test('user should have name property', () => {
 expect(hasName).toBeTruthy()
})

test('user should have surname using prototype', () => {
 expect(hasSurname).toBeTruthy()
})
Enter fullscreen mode Exit fullscreen mode

❌ FAIL user should have name property
❌ FAIL user should have surname using prototype

code

// hasOwnProperty overridden
const client = {
  name: 'A',
  surname: 'B',
  hasOwnProperty() { return false }
}
const hasClientName = client.hasOwnProperty('name')
const hasClientSurname = Object.prototype.hasOwnProperty.call(client, 'surname')
Enter fullscreen mode Exit fullscreen mode

test

test('client should have name property', () => {
 expect(hasClientName).toBeTruthy()
})

test('client should have surname using prototype', () => {
 expect(hasClientSurname).toBeTruthy()
})
Enter fullscreen mode Exit fullscreen mode

❌ FAIL client should have name property
✅ PASS client should have surname using prototype

Top comments (0)