最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - jslint - Don't make functions within a loop - Stack Overflow

programmeradmin4浏览0评论

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.

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.

Share Improve this question edited May 23, 2017 at 12:18 CommunityBot 11 silver badge asked Mar 27, 2013 at 17:02 HarpsHarps 6728 silver badges18 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 9

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) plain 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!

The problem with functions in loops is: this,

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

Will be interpretted as:

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

Because of variable hoisting. All declarations will be moved to the top of the scope (ie. function). So it doesn't actually make sense to define a function in a for-loop.

If you want to bind to the counter in a for-loop simply make a closure.

Just to be clear:

$("..").each(function () {
    for(..) {
    }
});

is fine.

for(..) {
    $("..").each(function () {

    });
}

is not fine because it's equivalent to this:

var my_func;
for(..) {
    my_func = function () {
        // ..
    }
    $("..").each(my_func);
}

It already sounds like the problem is more with the warning than with your code. Yeah it'll be nice to pass the JSLint test without warnings but some of them can be unreasonable and cause unnecessary code refactorization.

The discussion in this Q&A is relevant: Should I use JSLint or JSHint JavaScript validation? Other lint tools are available with more flexibility than JSLint so you can continue to be productive with your personal coding preferences, not necessarily Crockford's personal coding preferences.

I suggest you consider using another tool to lint your JavaScript and don't sacrifice readability or maintainability of your code.

发布评论

评论列表(0)

  1. 暂无评论