Jshint: loopfunc & let/const

Created on 15 Feb 2017  ·  7Comments  ·  Source: jshint/jshint

Some issues (#1301 and #2225, maybe others) states that this was solved, but 2.9.4 still warn about function in loops with the following:

const a = [], b = [];
for (let i in b) a.push(() => i);
for (let i of b) a.push(() => i);
for (let i = 0; i < 10; i++) a.push(() => i);

let i = 0;
while (i++ < 10) a.push(() => i);
P2

Most helpful comment

I will be utilizing @stevenventimiglia's method, wrapping my "offending" function with in-line configurations, turning the loopfunc lenience on and off where I know my code is referentially sound.

That said, I thought I'd provide one further example to highlight where this rule has some gaps:

function foo(myLoopArr)
{
    /* globals Promise: false */
    for(let val in myLoopArr)
    {
        const myPromArr = [];
        myPromArr.push(function() {
            return new Promise();
        });
    }
}

The above function doesn't do anything of any use. But, importantly, none of the values in the loop reference any variables outside of the loop. And yet jshint throws the warning:

 myPromArr.push(function() {
                                ^ Functions declared within loops referencing an outer scoped variable may lead to confusing semantics.

Just thought I'd stoke the fire by pointing out that this warning may be called on lexically sound situations.

All 7 comments

Thanks for the report! Despite the comments on the issues you've referenced, I
can't find a version of JSHint where this behavior was ever relaxed properly.

Also: the final example you shared is a special case that should not be
allowed:

let i = 0;
while (i++ < 10) a.push(() => i);

The fact that the i binding happens to be lexically scoped doesn't actually
protect against the mistake loopfunc was originally implemented to avoid.
Authors and readers of code like that may expect that each function has a
dedicated i binding, but in fact, they all share the same binding. If anyone
is able to help out with this bug, please don't forget to account for that
case.

Also: the final example you shared is a special case that should not be allowed:

You're completely right... How silly of me... ^__^
About the real issue, do we have any expectation of getting this implemented?

We do not have any expectation at the moment. Would you like to help out?

Just to say for anyone encountering this: This issue remains in jshint 2.9.5.

The error code it produces is W083.

@overlookmotel - Been experiencing the same issue for over five years.

My recommendation is to either place /*jshint loopfunc: true */ at the top of your .js file, or add "loopfunc" : true, to your .jshintrc settings. It doesn't really fix the issue, but if it hasn't been resolved after 5+ years have passed, it's not something that can or will be addressed any time soon.

I will be utilizing @stevenventimiglia's method, wrapping my "offending" function with in-line configurations, turning the loopfunc lenience on and off where I know my code is referentially sound.

That said, I thought I'd provide one further example to highlight where this rule has some gaps:

function foo(myLoopArr)
{
    /* globals Promise: false */
    for(let val in myLoopArr)
    {
        const myPromArr = [];
        myPromArr.push(function() {
            return new Promise();
        });
    }
}

The above function doesn't do anything of any use. But, importantly, none of the values in the loop reference any variables outside of the loop. And yet jshint throws the warning:

 myPromArr.push(function() {
                                ^ Functions declared within loops referencing an outer scoped variable may lead to confusing semantics.

Just thought I'd stoke the fire by pointing out that this warning may be called on lexically sound situations.

@andrew-st-angelo-77media Good job reporting that. I'm just getting the exact same error, even though my function does not reference any outer scoped variables. I hope this will be taken care off.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

stefanuddenberg picture stefanuddenberg  ·  7Comments

ghost picture ghost  ·  5Comments

TheSavior picture TheSavior  ·  3Comments

jugglinmike picture jugglinmike  ·  6Comments

mcandre picture mcandre  ·  3Comments