Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jslint - Don't make functions within a loop

Refering to this topic: Don't make functions within a loop. - jslint error

How would you handle a jquery .each(function () {...} within a for loop? knowing that i need the context of the "for" in my "each" function. Sure I could map every required to parameters to a function a function declared outside of the loop but from my perspective, it impacts the readability.

Any thoughts?

Thanks in advance.

like image 886
Harps Avatar asked Mar 27 '13 17:03

Harps


1 Answers

Well, you can keep the context of the for in your loop, as everything in the for is actually in the same context as a function declared at the start.

So let's take Frits' example, but first let's make this fully JSLint happy (minus the function called in the loop error) first.

/*global console*/
var my_func, i, list;
for (i = 0; i < list.length; i+= 1) {
    my_func = function (i) {
        console.log(i);
    };
    my_func(i);
}

Note that each time you iterate the loop, you're redeclaring the my_func function. That's not cool! Why re-declare the same function over and over?

Declare it earlier, like this:

/*global console*/
var my_func, i, list;

my_func = function (i) {
    console.log(i);
};

for (i = 0; i < list.length; i+= 1) {
    my_func(i);
}

Success. Now you don't create a function with each iteration. And, as JSLint helps you realize by pushing all your var declarations to the top, you still get to have the same context.


EDIT: As @Flame points out, you don't have to declare the function early with jQuery each and can use an anonymous function, but it's not a bad idea to declare early, especially if you're doing to reuse the logic in multiple each calls. The main take-homes are to understand that 1.) The early declaration practice still has advantages, and 2.) jQuery's still going to send along arguments to your function (here, what we're calling index), though JSLint will not (and should not) complain about anonymous functions used in eachs (jQuery sauce here).

It is initially a little more unintuitive if you're used to the anonymous $.each(function() {}); construct, but it's just as easy.

/*global alert, $ */
$( "li" ).each(function( index ) {
    alert( index + ": " + $(this).text() );
});

... turns into...

/*global $, alert */
var fnOutside = function(index) {
    alert( index + ": " + $(this).text() );
};
$( "li" ).each(fnOutside);

That might be confusing briefly because the function call doesn't have parameters, but jQuery is what's pushing the "index" parameter to the function. You could just grab the contextual arguments array to see that it's still pushed in there if you wanted to leave the naming out.

Fiddle-ige

That is to say, the for construct doesn't create a new closure. That might be worrying you. It's no problem!

like image 56
ruffin Avatar answered Sep 22 '22 10:09

ruffin