How to determine whether an object has a given property in JavaScript

JavascriptObject

Javascript Problem Overview


How can I determine whether an object x has a defined property y, regardless of the value of x.y?

I'm currently using

if (typeof(x.y) !== 'undefined')

but that seems a bit clunky. Is there a better way?

Javascript Solutions


Solution 1 - Javascript

Object has property:

If you are testing for properties that are on the object itself (not a part of its prototype chain) you can use .hasOwnProperty():

if (x.hasOwnProperty('y')) { 
  // ......
}

Object or its prototype has a property:

You can use the in operator to test for properties that are inherited as well.

if ('y' in x) {
  // ......
}

Solution 2 - Javascript

If you want to know if the object physically contains the property @gnarf's answer using hasOwnProperty will do the work.

If you're want to know if the property exists anywhere, either on the object itself or up in the prototype chain, you can use the in operator.

if ('prop' in obj) {
  // ...
}

Eg.:

var obj = {};

'toString' in obj == true; // inherited from Object.prototype
obj.hasOwnProperty('toString') == false; // doesn't contains it physically

Solution 3 - Javascript

Underscore.js or Lodash

if (_.has(x, "y")) ...

:)

Solution 4 - Javascript

You can trim that up a bit like this:

if ( x.y !== undefined ) ...

Solution 5 - Javascript

One feature of my original code

if ( typeof(x.y) != 'undefined' ) ...

that might be useful in some situations is that it is safe to use whether x exists or not. With either of the methods in gnarf's answer, one should first test for x if there is any doubt if it exists.

So perhaps all three methods have a place in one's bag of tricks.

Solution 6 - Javascript

includes

Object.keys(x).includes('y');

The Array.prototype.includes() method determines whether an array includes a certain value among its entries, returning true or false as appropriate.

and

Object.keys() returns an array of strings that represent all the enumerable properties of the given object.

.hasOwnProperty() and the ES6+ ?. -optional-chaining like: if (x?.y) are very good 2020+ options as well.

Solution 7 - Javascript

ES6+:

There is a new feature on ES6+ that you can check it like below:

if (x?.y)

Actually, the interpretor checks the existence of x and then call the y and because of putting inside if parentheses the coercion happens and x?.y converted to boolean.

Solution 8 - Javascript

Since question was regarding clunkiness of property checking, and one regular usecase for that being validation of function argument options objects, thought I'd mention a library-free short way of testing existence of multiple properties. Disclaimer: It does require ECMAScript 5 (but IMO anyone still using IE8 deserves a broken web).

function f(opts) {
  if(!["req1","req2"].every(opts.hasOwnProperty, opts)) {
      throw new Error("IllegalArgumentException");
  }
  alert("ok");
}
f({req1: 123});  // error
f({req1: 123, req2: 456});  // ok

Solution 9 - Javascript

const data = [{"b":1,"c":100},{"a":1,"b":1,"c":150},{"a":1,"b":2,"c":100},{"a":2,"b":1,"c":13}]

const result = data.reduce((r, e)  => {
  r['a'] += (e['a'] ? e['a'] : 0)
    r['d'] += (e['b'] ? e['b'] : 0)
  r['c'] += (e['c'] ? e['c'] : 0)

  return r
}, {'a':0, 'd':0, 'c':0})

console.log(result)
`result` { a: 4, d: 5, c: 363 }

Solution 10 - Javascript

Unlike other examples in this thread, this implementation only asserts that object has a property for which we are checking.

const hasOwnProperty = <X extends {}, Y extends PropertyKey>(
  object: X,
  property: Y
): object is Record<Y, unknown> & X => {
  return object.hasOwnProperty(property);
};

Here is an example of it being used to identify a branch that has the desired property.

const hasOwnProperty = <X extends {}, Y extends PropertyKey>(
  object: X,
  property: Y
): object is Record<Y, unknown> & X => {
  return object.hasOwnProperty(property);
};

type PaidProjectFeeType = 'FIXED_PRICE' | 'RATE' | '%future added value';

const PAID_PROJECT_FEE_TYPE_LABELS: Record<
  'FIXED_PRICE' | 'RATE',
  string
> = {
  FIXED_PRICE: 'Fixed Price',
  RATE: 'Rate',
};

export const getPaidProjectFeeTypeLabel = (
  feeType: PaidProjectFeeType
): string => {
  if (hasOwnProperty(PAID_PROJECT_FEE_TYPE_LABELS, feeType)) {
    PAID_PROJECT_FEE_TYPE_LABELS[feeType];
  }

  throw new Error('test');
};

https://tsplay.dev/m0LBOm

Annoyingly, the catch is that now PAID_PROJECT_FEE_TYPE_LABELS is assumed to be:

Record<PaidProjectFeeType, unknown> & Record<"FIXED_PRICE" | "RATE", string>

i.e. You cannot return the result because a possible value of X[Y] is unknown. This is useful when you need to assert that object has a desired property, but you will need to add further assertions to ensure that the result is what you intend.

There is a better way, though.

We will need two utilities:

export const keys = <T extends Record<string, unknown>>(
  object: T
): Array<keyof T> => {
  return Object.keys(object);
};

keys gives us a typed array of object property names.

export const includes = <C extends M, M>(
  collection: readonly C[],
  member: M
): member is C => {
  return collection.includes(member as C);
};

includes allows to assert that a property is a member of a read-only array. You can read more about includes in this blog post.

export const keys = <T extends Record<string, unknown>>(
  object: T
): Array<keyof T> => {
  return Object.keys(object);
};

export const includes = <C extends M, M>(
  collection: readonly C[],
  member: M
): member is C => {
  return collection.includes(member as C);
};

type PaidProjectFeeType = 'FIXED_PRICE' | 'RATE' | '%future added value';

const PAID_PROJECT_FEE_TYPE_LABELS: Record<
  'FIXED_PRICE' | 'RATE',
  string
> = {
  FIXED_PRICE: 'Fixed Price',
  RATE: 'Rate',
};

export const getPaidProjectFeeTypeLabel = (
  feeType: PaidProjectFeeType
): string => {
  if (includes(keys(PAID_PROJECT_FEE_TYPE_LABELS), feeType)) {
    return PAID_PROJECT_FEE_TYPE_LABELS[feeType];
  }

  throw new Error('test');
};

https://tsplay.dev/N7gLDN

In short, this approach allows us to narrow down feeType value to the values present in keys(PAID_PROJECT_FEE_TYPE_LABELS), which then allows us to access the property value.

This approach works the best, with a caveat that technically keys implementation is not run-time safe. There is (mostly theoretical) scenario where values returned runtime are different than those inferred using tsc.

Solution 11 - Javascript

In addition to other answers I would like to suggest using the Object.hasOwn() method for checking if the specified object has the specified property as its own property (meaning on the object itself) you can use the new Object.hasOwn() method which is a static method which returns true if the specified object has the specified property as its own property. If the property is inherited, or does not exist, the method returns false.

const person = { name: 'dan' };

console.log(Object.hasOwn(person, 'name'));// true
console.log(Object.hasOwn(person, 'age'));// false

const person2 = Object.create({gender: 'male'});

console.log(Object.hasOwn(person2, 'gender'));// false

It is recommended to this method use over the Object.hasOwnProperty() because it also works for objects created by using Object.create(null) and for objects that have overridden the inherited hasOwnProperty() method. Although it's possible to solve these kind of problems by calling Object.prototype.hasOwnProperty() on an external object, Object.hasOwn() overcome these problems, hence is preferred (see examples below)

let person = {
  hasOwnProperty: function() {
    return false;
  },
  age: 35
};

if (Object.hasOwn(person, 'age')) {
  console.log(person.age); // true - the remplementation of hasOwnProperty() did not affect the Object
}

let person = Object.create(null);
person.age = 35;
if (Object.hasOwn(person, 'age')) {
  console.log(person.age); // true - works regardless of how the object was created
}

More about Object.hasOwn can be found here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn

Browser compatibility - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn#browser_compatibility

Checking if the specified property exists on the object itself or up in the prototype chain could be verified via the in operator as other answers suggested.

Solution 12 - Javascript

Why not simply:

if (typeof myObject.myProperty == "undefined") alert("myProperty is not defined!");

Or if you expect a specific type:

if (typeof myObject.myProperty != "string") alert("myProperty has wrong type or does not exist!");

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser213154View Question on Stackoverflow
Solution 1 - JavascriptgnarfView Answer on Stackoverflow
Solution 2 - JavascriptChristian C. SalvadóView Answer on Stackoverflow
Solution 3 - JavascriptnackjicholsonView Answer on Stackoverflow
Solution 4 - JavascriptjpsimonsView Answer on Stackoverflow
Solution 5 - Javascriptuser213154View Answer on Stackoverflow
Solution 6 - JavascriptJ RodView Answer on Stackoverflow
Solution 7 - Javascriptuser14415508View Answer on Stackoverflow
Solution 8 - JavascriptsttView Answer on Stackoverflow
Solution 9 - JavascriptRahul GoyalView Answer on Stackoverflow
Solution 10 - JavascriptGajusView Answer on Stackoverflow
Solution 11 - JavascriptRan TurnerView Answer on Stackoverflow
Solution 12 - JavascriptDomeView Answer on Stackoverflow