0

I am wondering if someone could help me to understand why it is necessary to add the following line...

if (!obj.hasOwnProperty(key)) continue;

... in the following method:

extend: function(obj) {
  // shallow copy
  for (var key in obj) {
    if (!obj.hasOwnProperty(key)) continue;
      this[key] = obj[key];
  }
}
Ian
  • 50,146
  • 13
  • 101
  • 111
user2111743
  • 69
  • 1
  • 7
  • Is the question *why* that line is necessary? Do you understand what [it](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/hasOwnProperty) does? – Bergi Apr 12 '13 at 15:10
  • 1
    possible duplicate of [Why is using "for...in" with array iteration such a bad idea?](http://stackoverflow.com/questions/500504/why-is-using-for-in-with-array-iteration-such-a-bad-idea) < don't be misled by the title, lots of excellent examples about what `hasOwnProperty` is for, – dm03514 Apr 12 '13 at 15:11
  • yes, I do not understand why, as it seems to me the object would always have the key as a property. – user2111743 Apr 12 '13 at 15:12
  • @user2111743 " The purpose of the for-in statement is to enumerate over object properties, this statement will go up in the prototype chain, enumerating also inherited properties, thing that sometimes is not desired." there are tons of posts on SO and internet about reasons to use `hasOwnProperty` – dm03514 Apr 12 '13 at 15:15
  • 1
    @dm03514: It does have good answers, but they do fairly center on the array-ness of the question. :-) – T.J. Crowder Apr 12 '13 at 15:16
  • From the MDN docs for `hasOwnProperty` - "this method does not check down the object's prototype chain". And from the MDN docs for `for in` - "The loop will iterate over all enumerable properties of the object itself and those the object inherits from its constructor's prototype" – Ian Apr 12 '13 at 15:24

1 Answers1

2

When you use for-in to loop through the names of the properties of an object, you see all of the enumerable properties, including those the object inherits from its prototype. It would appear that the person implementing that method didn't want to copy properties inherited from the prototype, and so only included ones that the object itself directly owns.

Here's an example:

function Thing(name) {
    this.name = name;
}
Thing.prototype.speak = function() {
    console.log("I'm " + this.name);
};
Thing.prototype.infoForAllThings = 42;
var t1 = new Thing("Fred");
console.log(t1.name);             // "Fred"
console.log(t1.infoForAllThings); // "42"
t1.speak();                       // "I'm Fred"
var t2 = extend(t1);              // (Where `extend` is like your function,
                                  // but returns the object rather than using `this`
console.log(t2.name);             // "Fred"
console.log(t2.infoForAllThings); // "undefined"
t2.speak();                       // Error

In the above, t1 inherits the infoForAllThings and speak properties from its prototype, which gets set to Thing.prototype when t1 is created. But the extend function uses hasOwnProperty to filter those out, so doesn't copy them to the copy it creates, and so they don't exist on t2. t2 has name because that's been assigned directly to the object, it doesn't come from the prototype, but the others come from the prototype and so don't get copied.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875