369

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?

royhowie
  • 11,075
  • 14
  • 50
  • 67
  • Don't "call" `typeof` with `()`, [it is an operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof), not a function – Parzh from Ukraine May 27 '21 at 11:42

12 Answers12

670

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) {
  // ......
}
gnarf
  • 105,192
  • 25
  • 127
  • 161
88

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
Community
  • 1
  • 1
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
16

Underscore.js or Lodash

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

:)

nackjicholson
  • 4,557
  • 4
  • 37
  • 35
  • 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` – nackjicholson Nov 03 '13 at 22:13
14

You can trim that up a bit like this:

if ( x.y !== undefined ) ...
jpsimons
  • 27,382
  • 3
  • 35
  • 45
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.

  • 1
    You could always use `(x && x.hasOwnProperty('y'))` or `(x && 'y' in x)` – gnarf Aug 04 '10 at 21:50
  • I agree, testing for x should be a separate case on it's own. Also yields better error reporting. – b01 Aug 18 '11 at 14:44
  • That failed for me. If x is undefined then typeof(x.y) returns a `ReferenceError` rather than the string 'undefined' – Craig Dec 18 '14 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.

J Rod
  • 621
  • 1
  • 8
  • 14
2

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.

Ran Turner
  • 14,906
  • 5
  • 47
  • 53
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
stt
  • 342
  • 2
  • 7
1

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.

  • 9
    What if `x.y` exists and it is a *falsy* value. – Danilo Gómez Dec 14 '20 at 09: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 Jan 24 '23 at 03:41
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.

Gajus
  • 69,002
  • 70
  • 275
  • 438
  • 1
    Thank you for taking the time to answer! Would be nice with an explanation of your answer and not just code. – softarn Oct 20 '21 at 06: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!");
Dome
  • 7
  • 2
    Because its bad to read and not type strict. I must ask to you: why not simply `x.hasOwnProperty('y')`? – fabpico Aug 21 '17 at 07:27