82

Possible Duplicate:
How do I check if an object has a specific property in JavaScript?

I found the following snippet in Twitter's JavaScript files. Why do they need to call the hasOwnProperty function to see dict has the key property? The for loop is running for each 'key' in 'dict' which means 'dict' has 'key'. Am I missing a point?

function forEach(dict, f) {
    for (key in dict) {
        if (dict.hasOwnProperty(key))
            f(key, dict[key]);
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
scusyxx
  • 1,226
  • 1
  • 8
  • 9
  • 3
    It's well-explained here: http://stackoverflow.com/a/136411/27512 – kevingessner Oct 04 '12 at 20:57
  • Seems like `key` is global where is this code from, can you post a link to it? – elclanrs Oct 04 '12 at 20:58
  • @elclanrs I was wrong. This code is from Chrome's utils.js – scusyxx Oct 04 '12 at 21:11
  • 1
    @elclanrs it is more probable that he just don't know that his code is creating this global, it is very easy to forget the `var` in for in loops, **edit**: oh, I just read that it is not his code... interesting – ajax333221 Oct 04 '12 at 22:08
  • He must've written it and forgot about it. It's improbable that google code misses the brackets and forgets `var`. – elclanrs Oct 04 '12 at 22:11
  • I would suggest naming such function `forIn` to avoid confusion with `Array.forEach`. It may be good idea to define it on `Object.prototype` via `Object.defineProperty` if you don't care about IE 8, and allow it to accept iterating function of `(key, value)` signature. This would allow for more expressive code, especially in `es6` – Dr.Strangelove May 27 '16 at 09:34
  • You need to swap the order of arguments in call to `f`, i.e. `f(dict[key], key)` – Sohail Si Mar 19 '21 at 17:11

4 Answers4

83

Because if you don't, it will loop through every property on the prototype chain, including ones that you don't know about (that were possibly added by somebody messing with native object prototypes).

This way you're guaranteed only the keys that are on that object instance itself.

blockhead
  • 9,655
  • 3
  • 43
  • 69
  • 2
    I just don't understand how a so popular and rapidly evolving language like JS after so many years and standards still doesn't a proper loop for object iteration where you don't have to call `hasOwnProperty()` on every single loop step. – Sceptical Jule Jan 22 '20 at 15:44
  • 6
    @ScepticalJule `for..in` is specifically to get enumerable properties including inherited ones. If you want only *enumerable own* properties, you can use for `for (const key of Object.keys(obj))`. [Enumerability and ownership of properties table](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties#detection_table) – adiga Apr 28 '21 at 10:56
  • 1
    @ScepticalJule This is my problem with web development in general. Even with how popular it has become, all webdev technologies of today just keep building layers on top of crappy 30 year old tech. I wish we'd just ditch it all and make something that's actually powerful, intuitive and actually geared towards what we need in this day and age. – Johan Wintgens Jul 16 '21 at 13:13
36

The hasOwnProperty method lets you know if a property is directly on an instance of an object or inherited from its prototype chain.

Consider the following

function ObjWithProto() {
    this.foo = 'foo_val';
}

ObjWithProto.prototype = {bar: 'bar_val'};

var dict = new ObjWithProto();
dict.foobar = 'foobar_val';

I.e., you have an Object dict with properties foo and foobar that also inherits a property bar from its prototype chain.

Now run it through (a modified version of) your code:

function forEach(dict) {
    var key;
    for (key in dict) {
        if (dict.hasOwnProperty(key)) 
            console.log('has', key, dict[key]);
        else 
            console.log('not', key, dict[key]);
    }
}
forEach(dict);

You will see

has foo foo_val
has foobar foobar_val
not bar bar_val

This lets you separate properties that an object has itself and those it has inherited (which are usually methods that aren't relevant to the loop).

Furthermore, if you now do dict.bar = 'new_bar_val';, the last result will change to has bar new_bar_val, letting you distinguish even between properties of the same name as those inherited.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Paul S.
  • 64,864
  • 9
  • 122
  • 138
5

Every object in JavaScript is a dictionary. This means that "toString" and every other method is a key of every Object:

var myObj = {};
console.log(myObj["toString"]);

But this function is inherited from Object class, so hasOwnProperty tells you if this key is owned by the dictionary or if it is inherited.

"toString" in myObj; // true
myObj.hasOwnProperty("toString") // false
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
A. Matías Quezada
  • 1,886
  • 17
  • 34
1

blockhead is right here. For example, the Prototype.js framework used to extend native arrays with extra helper methods (I do not know the situation with current versions of a framework).

Thus straight usage of "for (key in dict)" would return all the elements of the div plus references to helper methods. Which is kind of unexpected :)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
d1pr3d
  • 76
  • 4