3
\$\begingroup\$

I have a function that looks through an array of objects and returns an array of all objects that have matching property and value pairs. This works fine but I always get the notification: "Don't make functions within a loop".

So is this a bad approach to use a function within a loop?

function where(collection, source) {
 var arr = [];
 var keys = Object.keys(source);
 // What's in a name?
 for(var i = 0; i < collection.length; i++){
 if(keys.every(function(x){return x in collection[i] && source[x] == collection[i][x];})){
 arr.push(collection[i]);
 }
 }
 return arr;
}
where([{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }], { last: "Capulet" });
SuperBiasedMan
13.5k5 gold badges37 silver badges62 bronze badges
asked Jan 7, 2016 at 12:48
\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

You'd be better off defining the function outside of the loop and calling it by passing it parameters. What the warning is referring to in this case is creating a new function object in a loop, meaning you create several anonymous functions, where 1 function would do. Creating a new function object in a loop like this can hurt performance.

answered Jan 7, 2016 at 12:59
\$\endgroup\$
4
\$\begingroup\$

As @Pimgd explained, it's not good to recreate an anonymous function in every iteration of a loop. Move the function outside of the loop:

function where(collection, source) {
 var arr = [];
 var keys = Object.keys(source);
 function match(x) {
 return x in collection[i] && source[x] == collection[i][x];
 }
 for (var i = 0; i < collection.length; i++) {
 if (keys.every(match)) {
 arr.push(collection[i]);
 }
 }
 return arr;
}

I suggest to go one step further. Instead of creating an array and appending to it, you can benefit from the Array.prototype.filter method:

function where(collection, search) {
 function filter(item) {
 function matchSearchValue(key) {
 return key in item && search[key] == item[key];
 }
 return Object.keys(search).every(matchSearchValue);
 }
 return collection.filter(filter);
}

Finally, notice how I renamed everything to better explain their purpose.

answered Jan 7, 2016 at 13:49
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.