All Downloads are FREE. Search and download functionalities are using the official Maven repository.

rules.jshint.W083.html Maven / Gradle / Ivy

Go to download

Consume reports generated by jshint for code quality. Also consume reports for code duplication (either simian or cpd). Consumes the unit/integration tests reports (generated by Jasmin) coverage report (lcov generated by Istanbul). The information generated by reports are added in Sonar

There is a newer version: 2.1.0
Show newest version

    

When do I get this error?

The "Don't make functions within a loop" error is thrown when JSLint, JSHint and ESLint encounter a function expression in a for, while or do statement body. In the following example we attempt to add a click event listener to each element with a given class name. The event handler is intended to overwrite the contents of the clicked element with the value of i at a specific iteration of the loop:

x
 
1
/*jslint browser: true, plusplus: true */
2
3
var elems = document.getElementsByClassName("myClass"), i;
4
5
for (i = 0; i < elems.length; i++) {
6
    elems[i].addEventListener("click", function () {
7
        "use strict";
8
        this.innerHTML = i;
9
    });
10
}
11
JSLint found 5 errorsVersion 2015-09-23
Line 0:Bad option 'plusplus'.
Line 4:Unexpected 'for'.
Line 4:Expected '+= 1' and instead saw '++'.
Line 5:Don't make functions within a loop.
Line 7:Unexpected 'this'.

Why do I get this error?

This error is raised to highlight code that may not work as you expect it to and could also indicate misunderstanding of how the language works. Your code may run without any problems if you do not fix this error, but in some situations it could behave unexpectedly.

There are a couple of fundamental problems with functions in loops. Imagine elems in the above example contains 5 elements. You might expect a click on the second element to set that element's content to 1 (not 2 since the loop starts at 0). However that isn't what happens. Instead, the element is overwritten with 4 which is the final value of i when the loop finished. This happens because each function retains a reference to the same copy of i. We can get around this by forcing each function to take its own copy of i at whatever value it has at that time:

13
 
1
/*jslint browser: true, plusplus: true */
2
3
var elems = document.getElementsByClassName("myClass"), i;
4
5
for (i = 0; i < elems.length; i++) {
6
    (function (iCopy) {
7
        "use strict";
8
        elems[i].addEventListener("click", function () {
9
            this.innerHTML = iCopy;
10
        });
11
    }(i));
12
}
13
JSLint found 5 errorsVersion 2015-09-23
Line 0:Bad option 'plusplus'.
Line 4:Unexpected 'for'.
Line 4:Expected '+= 1' and instead saw '++'.
Line 5:Don't make functions within a loop.
Line 8:Unexpected 'this'.

What we have now captures the value of i at each iteration of the loop. This happens because JavaScript passes arguments to functions by value. This means that iCopy within the capturing function is not related to i in any way (except for the fact that they happen to have the same value at that point in time). If i changes later (which it does - on the next iteration of the loop) then iCopy is not affected.

This will work as we expect it to but the problem now is that the JavaScript interpreter will create an instance of the capturing function per loop iteration. It has to do this because it doesn't know if the function object will be modified elsewhere. Since functions are standard JavaScript objects, they can have properties like any other object, which could be changed in the loop. Thus by creating the function in the loop context, you cause the interpreter to create multiple function instances, which can cause unexpected behavior and performance problems. To fix the issue, we need to move the function out of the loop:

15
 
1
/*jslint browser: true, plusplus: true */
2
3
var elems = document.getElementsByClassName("myClass"), i;
4
5
function makeClickHandler(i) {
6
    "use strict";
7
    return function () {
8
        this.innerHTML = i;
9
    };
10
}
11
12
for (i = 0; i < elems.length; i++) {
13
    elems[i].addEventListener("click", makeClickHandler(i));
14
}
15
JSLint found 4 errorsVersion 2015-09-23
Line 0:Bad option 'plusplus'.
Line 7:Unexpected 'this'.
Line 11:Unexpected 'for'.
Line 11:Expected '+= 1' and instead saw '++'.

In JSHint 1.0.0 and above you have the ability to ignore any warning with a special option syntax. The identifier of this warning is W083. This means you can tell JSHint to not issue this warning with the /*jshint -W083 */ directive. You can also set the loopfunc option to true.

In ESLint the rule that generates this warning is named no-loop-func. You can disable it by setting it to 0, or enable it by setting it to 1.





© 2015 - 2025 Weber Informatics LLC | Privacy Policy