394

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?

3

12 Answers 12

710

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) {
  // ......
}
5
  • 37
    Or even better — Object.prototype.hasOwnProperty.call(x, 'y'), so that property named "hasOwnProperty" would not conflict with inspection process ;)
    – kangax
    Commented Dec 24, 2009 at 14:03
  • 7
    Or even shorter — {}.hasOwnProperty.call(x, 'y').
    – axmrnv
    Commented Jan 27, 2019 at 20:46
  • 2
    eslint.org/docs/rules/no-prototype-builtins
    – malat
    Commented Jun 19, 2020 at 13:28
  • 7
    Use Object.hasOwn() these days
    – user3064538
    Commented Nov 14, 2022 at 6:11
  • 2
    If using TypeScript, guarding with 'y' in x clears error ts(2551), "Property 'y' does not exist on type 'foo'"
    – Vessel
    Commented May 4, 2024 at 22:02
96

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
1
  • 1
    Using 'prop' in obj is the best option because it also performs type narrowing so you have proper typing
    – Chris Barr
    Commented Jun 11, 2024 at 18:03
15

Underscore.js or Lodash

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

:)

1
  • 1
    Nope. It's just an alias for Object.prototype.hasOwnProperty.call(x, "y"). For arrays I think you might want Array.prototype.indexOf, _.indexOf, or _.contains Commented Nov 3, 2013 at 22:13
14

You can trim that up a bit like this:

if ( x.y !== undefined ) ...
4
  • 22
    That would fail with x = {y:undefined}
    – James
    Commented Dec 12, 2009 at 21:59
  • 22
    Does anyone need to distinguish between "not defined" and "defined to be undefined?"
    – jpsimons
    Commented Dec 12, 2009 at 22:25
  • 18
    @darkporter I do sometimes ;)
    – mjs
    Commented Jul 19, 2013 at 19:48
  • @jpsimons for and instance "defined to be undefined" is used by Firestore when saving document data. Commented Sep 10, 2020 at 2:44
6

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.

3
  • 1
    You could always use (x && x.hasOwnProperty('y')) or (x && 'y' in x)
    – gnarf
    Commented Aug 4, 2010 at 21:50
  • I agree, testing for x should be a separate case on it's own. Also yields better error reporting.
    – b01
    Commented Aug 18, 2011 at 14:44
  • That failed for me. If x is undefined then typeof(x.y) returns a ReferenceError rather than the string 'undefined'
    – Craig
    Commented Dec 18, 2014 at 22:40
6

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.

1
  • I would avoid this - Object.keys(x) will unnecessarily generate an array containing all keys of x - this should be avoidable. Commented Oct 17, 2023 at 21:51
3

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.

2
  • 9
    What if x.y exists and it is a falsy value. Commented Dec 14, 2020 at 9:14
  • @DaniloGómez The compiler first checks If x['y'] exists, if x has a property of ['y'] then the value of ['y'] will invoke where this value is true or false.
    – J Rod
    Commented Jan 24, 2023 at 3:41
3

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.

1

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
1

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.

1
  • 1
    Thank you for taking the time to answer! Would be nice with an explanation of your answer and not just code.
    – softarn
    Commented Oct 20, 2021 at 6:34
0
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 }
-3

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!");
1
  • 2
    Because its bad to read and not type strict. I must ask to you: why not simply x.hasOwnProperty('y')?
    – fabpico
    Commented Aug 21, 2017 at 7:27