0

I have read the following articles about how using has own property prevents you from enumerating over properties defined on the prototype of an object:

-MDN hasOwnProperty

-How do I check if an object has a property in JavaScript?

-for..in and hasOwnProperty

I think I get how the pattern works in general and why you would use it, but I still don't understand why, in the following code from CH 19 of Eloquent Javascript, the author has chosen to use this pattern...

function elt(name, attributes) {
  var node = document.createElement(name);
  if (attributes) {
    for (var attr in attributes)              
      if (attributes.hasOwnProperty(attr))       // <----------------
        node.setAttribute(attr, attributes[attr]);
  }
  for (var i = 2; i < arguments.length; i++) {
    var child = arguments[i];
    if (typeof child == "string")
      child = document.createTextNode(child);
    node.appendChild(child);
  }
  return node;
}

The use for this function, by the way, is:

It creates an element with the given name and attributes and appends all further arguments it gets as child nodes, automatically converting strings to text nodes.

Could someone walk me through this particular example?

Community
  • 1
  • 1
Goodword
  • 1,565
  • 19
  • 27
  • my guess is that there are default attributes for any dom element, and enumerating over attibutes for a dom element would unintentionally expose them...but I don't know – Goodword Nov 10 '14 at 22:54
  • it guards against un-expected members of the object's prototype that are iterated by for-in. that said, it also depends on attributes.hasOwnProperty, which is a poor idea because feeding it {value:5, hasOwnProperty:false} will blow it up. beter to use hasOwnProperty.call(attributes, attr) – dandavis Nov 10 '14 at 22:54
  • Typically you do not need `hasOwnProperty` in functions that deal with data. You need it only when dealing with enumerations of instances (i.e. objects with a custom prototype). – Bergi Nov 10 '14 at 23:00
  • `Object.getOwnPropertyNames(attributes).forEach(...)` seems much more elegant than the code example provided, and does pretty much the same thing. Also, I cannot imagine that it's slower than a `for` loop with calls to `.hasOwnProperty` in it. (Oh, who am I kidding. Some of these array methods are actually shockingly slow). – jongo45 Nov 11 '14 at 05:22

1 Answers1

1

The structure for (var attr in attributes) iterates all iterable properties, including items on the prototype.

If you only want to iterate properties that are actually assigned directly to the object, but not properties that are on the prototype, then you can filter them out using .hasOwnProperty() as the code you pointed to does. That code will skip any iterable properties on the prototype and will only iterate properties on the actual object itself.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • like what would this code accidentally enumerate over? – Goodword Nov 10 '14 at 22:54
  • @Goodword - what type of object is `attributes`? You don't show that so I don't know what it is. One usual thing you are avoiding with `.hasOwnProperty()` is iterable methods added to the core object. You can insert a `console.log(attributes[attr])` before the `.hasOwnProperty()` line to see everything that is there. – jfriend00 Nov 10 '14 at 22:55
  • the function gets fed an object with css-style attributes--something like `{width: 500, height: 300}` – Goodword Nov 10 '14 at 22:57
  • add a copy prototype.js and feed it an array as attributes for an example. – dandavis Nov 10 '14 at 22:57
  • 1
    @Goodword - then it would be avoiding any iterable polyfill methods added to `Object.prototype`. Because some 3rd party libraries do this, if you want to write the safest possible code that is compatible with the most 3rd party libraries, then you add this extra check. – jfriend00 Nov 10 '14 at 22:58
  • @dandavis - yes iterable methods added to `Object.prototype`. – jfriend00 Nov 10 '14 at 22:59
  • 1
    @Goodword: it probably accomplishes nothing for your testing code, but it's a good idea to be safe instead of sorry in mixed code environments. – dandavis Nov 10 '14 at 22:59