title: Fill in missing properties in an array of objects
body: <p>What is the best way to fill in missing properties in an array of objects, such as this example:</p>
  
  <pre><code>[
      {
          name: 'Tom',
          number: '01234 567 890',
          website: 'http://www.tom.com'
      },
      {
          name: 'Richard',
          number '07777 666 555'
      },
      {
          name: 'Harry',
          website: 'http://www.harry.com'
      }
  ]
  </code></pre>
  
  <p>I need to add the missing properties with a null value, so that when I pass this array on to be rendered in something such as a HTML table or CSV file, everything lines up correctly. I was thinking of passing over the array twice, once to get all the possible properties, and a second time to add those missing properties with a null value to each object where it doesn't exist. Is there a better way to do this?</p>
  
  <p>EDIT: I won't know what the keys are until I have the data, it's coming from an API and the keys are not always requested explicitly.</p>
  
  <hr>
  
  <h2>My final solution</h2>
  
  <p>Thanks all, it seems the two pass approach is indeed the best approach. After I started to write this using the examples provided, I realised that the order of the properties wasn't being maintained. This is how I achieved filling in the missing props, and maintaining the correct order. Any suggestions for potential improvements are welcome.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var fillMissingProps = function(arr) {
      // build a list of keys in the correct order
      var keys = [];
      arr.forEach(function(obj) {
          var lastIndex = -1;
          Object.keys(obj).forEach(function(key, i) {
              if (keys.includes(key)) {
                  // record the position of the existing key
                  lastIndex = keys.lastIndexOf(key);
                  if (lastIndex &lt; i) {
                      // this key is in the wrong position so move it
                      keys.splice(i, 0, keys.splice(lastIndex, 1)[0]);
                      lastIndex = i;
                  }
              } else {
                  // add the new key in the correct position
                  // after the previous existing key
                  lastIndex++;
                  keys.splice(lastIndex, 0, key);
              }
          });
      });
  
      // build a template object with all props set to null
      // and in the correct position
      var defaults = {};
      keys.forEach(function(key) {
          defaults[key] = null;
      });
  
      // and update the array by overwriting each element with a
      // new object that's built from the template and the original object
      arr.forEach(function(obj, i, arr) {
          arr[i] = Object.assign({}, defaults, obj);
      });
  
      return arr;
  };
  
  /** TEST **/
  
  var currentArray = [
      {
          website: 'http://www.unknown.com'
      },
      {
          name: 'Tom',
          number: '01234 567 890',
          website: 'http://www.tom.com'
      },
      {
          title: 'Mr',
          name: 'Richard',
          gender: 'Male',
          number: '04321 666 555'
      },
      {
          id: '003ABCDEFGHIJKL',
          name: 'Harry',
          website: 'http://www.harry.com',
          mobile: '07890 123 456',
          city: 'Brentwood',
          county: 'Essex'
      }
  ];
  
  var newArray = fillMissingProps(currentArray);
  
  for (var i = 0; i &lt; newArray.length; i++) {
      for (var prop in newArray[i]) {
          console.log(prop + ": " + newArray[i][prop]);
      }
      console.log('---------');
  }</code></pre>
  </div>
  </div>
  </p>