64

I can not get around JSHint's error message. Here is the loop I am using:

for (i = 0; i < Collection.length; i += 4) {
    data.push({
        items : Collection.slice(i, i + 4).map(function(item) {
            return {
                id: item[0],
                title: item[1],
            };
        })
    });
}
Whymarrh
  • 13,139
  • 14
  • 57
  • 108
myTD
  • 1,459
  • 4
  • 17
  • 30

3 Answers3

122

You can just move the function outside the loop and pass a reference to it to map:

function mapCallback(item) {
    return {
        id : item[0],
        title : item[1],
    };
}
for (i = 0; i < Collection.length; i += 4) {
    data.push({
        items: Collection.slice(i, i + 4).map(mapCallback)
    });
}

Alternatively, you can use a JSHint directive to ignore function expressions inside loops. Just put this at the top of the file in question:

/*jshint loopfunc: true */
James Allardice
  • 164,175
  • 21
  • 332
  • 312
  • 8
    @Skyrim1 The reason for the warning is to avoid the bug frequently encountered if you were using `i` in an asynchronous callback (onclick or ajax). You're safe here, you can tell jshint to be quiet using James' suggestion – Ruan Mendes Oct 26 '12 at 07:18
  • Thank you so much.. I am just not allowed to check in my code when i get any type of jshint messages... This worked great! – myTD Oct 26 '12 at 07:23
  • 2
    If anyone happens to be using Sublime Text with SublimeLinter, you can change this setting in Package Settings -> SublimeLinter -> User - Settings, with "jshint_options": { "loopfunc": true } – evanmcd Feb 22 '13 at 03:23
  • 20
    If you are disabling the warning using the `/*jshint ... */` comment, it's safest to keep the comment inside that loop block instead of top of the file. This way you don't accidentally hide future issues in other parts of the file. – Nick Matantsev Dec 13 '13 at 02:05
  • 2
    /*jshint loopfunc: true */ is not effective :/ – moala Oct 15 '14 at 13:27
  • loopfunc doesn't achieve anything whatsoever – Dave Lawrence Feb 05 '15 at 16:27
  • @daveL - It's still [listed in the documentation](http://jshint.com/docs/options/#loopfunc). I'll try and test it out when I get a chance. – James Allardice Feb 05 '15 at 16:51
  • @JuanMendes This idiom seems to avoid the `i` in async callback: `for (var iBar = 0; iBar < Bars.length; iBar++) { BarFuncs[iBar] = function (idx) { return function () { BarFunc(idx, true); }; }(iBar); }` as the outer executes and the inner does not get scope with the last value of `iBar` from the loop – subsci Aug 23 '15 at 00:13
  • 4
    @moala, I put `/* jshint loopfunc: true */` as the first line inside my `for` loop, and the warning went away. – Don Kirkby Jan 22 '16 at 19:05
  • 1
    this is nice but how would you go about passing a second parameter to the mapCallback? Say you want to pass item but also "id" and the id isn't available outside of the loop. – KFE May 31 '17 at 15:09
  • To ignore, add `// eslint-disable-next-line` to the line before. – Simon Hutchison Aug 01 '18 at 00:23
6

Declaring a function in a loop is messy, and potentially error prone. Instead, define the function once, and then enter the loop.

var objMaker = function(item) {
    return {
        id : item[0],
        title : item[1],
    };
};

for (i = 0; i < Collection.length; i += 4) {
    data.push({
                  items : Collection.slice(i, i + 4).map(objMaker)
             });
}
Cory Kendall
  • 7,195
  • 8
  • 37
  • 64
5

People say "Declaring a function in a loop is messy and potentially error-prone", but functions within loops is what directly instructed in, for example, Array.prototype.forEach method. Just because the word "function" should theoretically mean defining it anew in every forEach call it does not mean it is actually defined each time by the Javascript engine.

The same goes for outer loops since engines have "lazy" processing of instructions. They are not going to redefine the whole forEach/Map/etc construct-instruction anew if nothing really changed about it, they will just feed new arguments to it.

The times of ancient JS engines which were clueless about such simple things as well as of code context are long gone. And yet we are getting this ancient warning which was conceived when functions were not yet capable of being passed as arguments as in the cases of forEach or Map.

DDRRSS
  • 306
  • 3
  • 8