0

Currently, I'm building an object from an array of objects with the following:

var popOverOptions = {
  defaultOption: true
}

if (a) {
  options.push({a: "b"});
}

if (c) {
  options.push({c: "d"});
}

// Loop through array of objects
for (var i = 0; i < options.length; i++) {
   // Add objects in array to popoverOptions object
   for (key in options[i]) {
     popoverOptions[key] = options[i][key]
   }
}

I'm thinking this could be optimized and I'm curious if there is a better way to write this, possibly using .reduce(), .forEach() or some other method.

3
  • You are iterating each option just once, so unless you are repeating keys in those options, there shouldn´t be a more performant way, just a shorter version Commented Mar 30, 2015 at 17:14
  • Two minor optimizations come to mind: 1. If there's a canonical list of attributes to be copied, iterate over these and then search the array for that attribute 2. If there's a canonical list and the last appearance wins, search from the end of the array and break once you find an appearance. Fundamentally, you need to check every object in at least some cases, so I don't see an obvious way to significantly improve efficiency. Commented Mar 30, 2015 at 17:15
  • 1) Worry about performance when it becomes an issue. 2) A for loop is about as performant as you can get when looping over an array. The only thing that is faster is no loop (unrolled). Commented Mar 30, 2015 at 17:16

3 Answers 3

3

In ECMAScript 6, you can use

Object.assign(popOverOptions, ...options);
Sign up to request clarification or add additional context in comments.

7 Comments

Note Object.assign only copies own properties, but your for...in loop also iterates inherited ones. Not sure if it's a problem.
Shorter, yes. More performant, not even close. In the only browser that currently supports Object.assign (Firefox 35+), this is about 45% slower than using a regular for loop - jsperf.com/loop-versus-assign/2
@Adam On my Nightly 39, a loop is 42% slower than Object.assign. Screenshot
Ah, I was looking at Object.assign at one point, forgot about it though. Thanks for the info and thanks Adam for the jsperf link, good to know.
@Oriol - I hope I'm not offending you, but are you sure you're reading the results correctly?
|
1

You can optimise the loop itself like this:

for (var i=0, n=options.length; i<n; ++i) {

This reduces the number of times you need to access options.length which is slower than reading it from a local.

A smaller optimisation:

for (var i=options.length-1; i--; /* empty */) {

Source: http://www.phpied.com/extreme-javascript-optimization/

2 Comments

The last time I measured it, caching the length had the same performance on Chrome, and a worse performance on Firefox.
@Oriol, this jsPerf shows a slight performance increase using caching in Chrome: jsperf.com/array-length-vs-cached
0

You can cache length for a slight speed improvement.

If the keys in your array are identical for each element, you can get twice the speed (in Chrome) by caching Object.keys(options[0]), and iterating through that.

Even if the keys aren't the same, you can still get approx. 25% increase in speed by iterating through Object.keys(options[i]).

var options= [];

for(var i = 0 ; i <= 1000 ; i++) {  //create array of objects with random numbers
  options[i]= {};
  for(var j = 0 ; j <= 5000 ; j++) {
    options[i][j]= Math.random();
  }
}

var popOverOptions = {};

function keyin() {
  var timer= new Date();
  for(var i = 0, leni = options.length ; i < leni; i++) {
    for(var key in options[i]) {
      popOverOptions[key] = options[i][key];
    }
  }
  alert((new Date()-timer)/1000+' seconds');
} //keyin

function objkeys(same) {
  var timer= new Date(),
      keys= Object.keys(options[0]);

  for(var i = 0, leni = options.length ; i < leni; i++) {
    if(!same) keys= Object.keys(options[i]);
    for(var key = 0, lenk = keys.length ; key < lenk ; key++) {
      popOverOptions[keys[key]] = options[i][keys[key]];
    }
  }
  alert((new Date()-timer)/1000+' seconds');
} //objkeys
<button onclick="keyin()">key in options</button><br>
<button onclick="objkeys(true)">Object.keys, same keys per element</button><br>
<button onclick="objkeys(false)">Object.keys, different keys per element</button>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.