title: Why are Objects not Iterable in JavaScript?
body: <p>Why are objects not iterable by default?</p>
  
  <p><strong>I see questions all the time related to iterating objects, the common solution being to iterate over an object's properties and accessing the values within an object that way. This seems so common that it makes me wonder why objects themselves aren't iterable.</strong></p>
  
  <p>Statements like the ES6 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of"><code>for...of</code></a> would be nice to use for objects by default. Because these features are only available for special "iterable objects" which don't include <code>{}</code> objects, we have to go through hoops to make this work for objects we want to use it for. </p>
  
  <blockquote>
    <p>The for...of statement creates a loop Iterating over <strong>iterable objects</strong>
    (including Array, Map, Set, arguments object and so on)...</p>
  </blockquote>
  
  <p>For example using an ES6 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*">generator function</a>:</p>
  
  <pre><code>var example = {a: {e: 'one', f: 'two'}, b: {g: 'three'}, c: {h: 'four', i: 'five'}};
  
  function* entries(obj) {
     for (let key of Object.keys(obj)) {
       yield [key, obj[key]];
     }
  }
  
  for (let [key, value] of entries(example)) {
    console.log(key);
    console.log(value);
    for (let [key, value] of entries(value)) {
      console.log(key);
      console.log(value);
    }
  }
  </code></pre>
  
  <p>The above properly logs data in the order I expect it to when I run the code in Firefox (which supports <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla">ES6</a>):</p>
  
  <p><img src="https://i.stack.imgur.com/SSJbr.png" alt="output of hacky for...of"></p>
  
  <p><strong>By default, <code>{}</code> objects are not iterable, but why? Would the disadvantages outweigh the potential benefits of objects being iterable? What are the issues associated with this?</strong></p>
  
  <p>In addition, because <code>{}</code> objects are different from "Array-like" collections and "iterable objects" such as <a href="https://developer.mozilla.org/en-US/docs/Web/API/NodeList"><code>NodeList</code></a>, <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection"><code>HtmlCollection</code></a>, and <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments"><code>arguments</code></a>, they can't be converted into Arrays.</p>
  
  <p>For example:</p>
  
  <p><code>var argumentsArray = Array.prototype.slice.call(arguments);</code> </p>
  
  <p>or be used with Array methods:</p>
  
  <p><code>Array.prototype.forEach.call(nodeList, function (element) {})</code>.</p>
  
  <p><strong>Besides the questions I have above, I would love to see a working example on how to make <code>{}</code> objects into iterables, especially from those who have mentioned the <code>[Symbol.iterator]</code>.</strong> This should allow these new <code>{}</code> "iterable objects" to use statements like <code>for...of</code>. Also, I wonder if making objects iterable allow them to be converted into Arrays.</p>
  
  <p>I tried the below code, but I get a <code>TypeError: can't convert undefined to object</code>.</p>
  
  <pre><code>var example = {a: {e: 'one', f: 'two'}, b: {g: 'three'}, c: {h: 'four', i: 'five'}};
  
  // I want to be able to use "for...of" for the "example" object.
  // I also want to be able to convert the "example" object into an Array.
  example[Symbol.iterator] = function* (obj) {
     for (let key of Object.keys(obj)) {
       yield [key, obj[key]];
     }
  };
  
  for (let [key, value] of example) { console.log(value); } // error
  console.log([...example]); // error
  </code></pre>