217

Do the following two statements produce the same output? Is there any reason to prefer one way to the other?

 if (key in object)

 if (object.hasOwnProperty(key))
Jonathan
  • 5,953
  • 1
  • 26
  • 35
Lorraine Bernard
  • 13,000
  • 23
  • 82
  • 134

9 Answers9

221

Be careful - they won't produce the same result.

in will also return true if key gets found somewhere in the prototype chain, whereas Object.hasOwnProperty (like the name already tells us), will only return true if key is available on that object directly (its "owns" the property).

Boaz
  • 19,892
  • 8
  • 62
  • 70
Andre Meinhold
  • 5,087
  • 3
  • 21
  • 29
  • 4
    what do you mean exactly for `in will also return true if key gets found somewhere in the prototype chain`. can you write an example? thanks. – Lorraine Bernard Nov 29 '12 at 19:20
  • 53
    @Lor: `({foo:"bar"}).hasOwnProperty("toString")` vs `"toString" in ({foo:"bar"})` – I Hate Lazy Nov 29 '12 at 19:24
  • What about `if(Object.property)` ? – nonNumericalFloat Oct 13 '22 at 16:20
  • @nonNumericalFloat if your object is `const obj = { message: '' }`, And you do `if(obj.message)` It will lead to false since `message` is `falsy` (empty strings are falsy). Never use this approach, As it is checking the value of property on object. – shubham Oct 16 '22 at 11:20
  • Crazy as how often I have seen that method to check existence/falsly values at the same time. So this means we should always use both. `if(obj.message)` & `({foo:"bar"}).hasOwnProperty("bar")` to check for non-null and existence ? – nonNumericalFloat Oct 17 '22 at 08:26
  • `if (obj.message)` will work fine to check _that the property has a truthy value_, which depends on the property first existing on the object. However, it should not be used to simply check that the property exists, as it will evaluate to false in cases where the property does in fact exist but has a falsy value. I believe this is what @shubham was getting at. – fenix.shadow Aug 31 '23 at 21:43
80

I'l try to explain with another example. Say we have the following object with two properties:

function TestObj(){
    this.name = 'Dragon';
}
TestObj.prototype.gender = 'male';

Let's create instance of TestObj:

var o = new TestObj();

Let's examine the object instance:

console.log(o.hasOwnProperty('name')); // true
console.log('name' in o); // true

console.log(o.hasOwnProperty('gender')); // false
console.log('gender' in o); // true

Conclusion:

  • in operator returns true always, if property is accessible by the object, directly or from the prototype

  • hasOwnProperty() returns true only if property exists on the instance, but not on its prototype

If we want to check that some property exist on the prototype, logically, we would say:

console.log(('name' in o) && !o.hasOwnProperty('name')); //false
console.log(('gender' in o) && !o.hasOwnProperty('gender')); //true - it's in prototype

Finally:

So, regarding to statement that these two conditions ...

if (key in object)
if (object.hasOwnProperty(key))

...produce the same result, the answer is obvious, it depends.

Dalibor
  • 1,024
  • 7
  • 5
34

in will also check for inherited properties, which is not the case for hasOwnProperty.

Angel Politis
  • 10,955
  • 14
  • 48
  • 66
xavier.seignard
  • 11,254
  • 13
  • 51
  • 75
32

In summary, hasOwnProperty() does not look in the prototype while in does look in the prototype.

Taken from O'Reilly High Performance Javascript:

You can determine whether an object has an instance member with a given name by using the hasOwnProperty() method and passing in the name of the member. To determine whether an object has access to a property with a given name, you can use the in operator. For example:

var book = {
    title: "High Performance JavaScript",
    publisher: "Yahoo! Press" 
};

alert(book.hasOwnProperty("title"));  //true
alert(book.hasOwnProperty("toString"));  //false
alert("title" in book); //true 
alert("toString" in book); //true

In this code, hasOwnProperty() returns true when “title” is passed in because title is an object instance; the method returns false when “toString” is passed in because it doesn’t exist on the instance. When each property name is used with the in operator, the result is true both times because it searches the instance and prototype.

Jonathan
  • 10,936
  • 8
  • 64
  • 79
Etienne Noël
  • 5,988
  • 6
  • 48
  • 75
10

You got some really great answers. I just want to offer something that will save you the need for checking "hasOwnProperty" while iterating an object.

When creating an object usually people will create it in this way:

const someMap = {}
// equivalent to: Object.create(Object.prototype)
// someMap.constructor will yield -> function Object() { [native code] }

Now, if you want to iterate through "someMap" you will have to do it this way:

const key
for(key in someMap ){
 if (someMap.hasOwnProperty(key)) { 
   // Do something
 }
}

We are doing so in order to avoid iterating over inherited properties.

If you intend to create a simple object that will only be used as a "map" (i.e. key - value pairs) you can do so like that:

const newMap = Object.create(null);
// Now, newMap won't have prototype at all.
// newMap.constructor will yield -> undefined

So now it will be safe to iterate like this:

for(key in cleanMap){
 console.log(key + " -> " + newMap [key]);
 // No need to add extra checks, as the object will always be clean
}

I learned this awesome tip here

asafel
  • 713
  • 1
  • 7
  • 14
2

The other form (called for in) enumerates the property names (or keys) of an object. On each iteration, another property name string from the object is assigned to the variable. It is usually necessary to test object.hasOwnProperty(variable) to determine whether the property name is truly a member of the object or was found instead on the prototype chain.

 for (myvar in obj) {
     if (obj.hasOwnProperty(myvar)) { ... } }

(from Crockford's Javascript: The Good Parts)

pjvandehaar
  • 1,070
  • 1
  • 10
  • 24
Jahan Zinedine
  • 14,616
  • 5
  • 46
  • 70
2

As other answers indicated, hasOwnProperty will check for an object own properties in contrast to in which will also check for inherited properties.

New method 2021 - Object.hasOwn() as a replacement for Object.hasOwnProperty()

Object.hasOwn() is intended as a replacement for Object.hasOwnProperty() and is a new method available to use (yet still not fully supported by all browsers like as you can see here - https://caniuse.com/?search=hasOwn )

Object.hasOwn() 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

Ran Turner
  • 14,906
  • 5
  • 47
  • 53
0

Another way to have only ownproperties is :

<script type="text/javascript">"use strict";
  const obj = Object.create({cle:"valeur"});
  obj.a = "aaa";
  obj.b = "bbb";
  obj.c = "ccc";

  for(let key=0 ; key < Object.keys(obj).length ; key++){
     if(Object.keys(obj)[key]==="cle")
     console.log(key , Object.keys(obj)[key] , Object.values(obj)[key]);
     // none

     if(Object.keys(obj)[key]==="b")
     console.log(key , Object.keys(obj)[key] , Object.values(obj)[key]);
     // 1   'b'   'bbb'

     console.log(key , Object.keys(obj)[key] , Object.values(obj)[key]);
     // 0   'a'   'aaa'
     // 1   'b'   'bbb'
     // 2   'c'   'ccc'
  }

  console.log(Object.getOwnPropertyDescriptor(obj,"cle"));
  // undefined

  console.log(Object.getOwnPropertyDescriptor(obj,"c"));
  // {value:'ccc', writable:true, enumerable:true, configurable:true}
</script>
-6

The first version is shorter (especially in minified code where the variables are renamed)

a in b

vs

b.hasOwnProperty(a)

Anyway, as @AndreMeinhold said, they do not always produce the same result.

Angel Politis
  • 10,955
  • 14
  • 48
  • 66
antonjs
  • 14,060
  • 14
  • 65
  • 91