Fork me on GitHub

JSLint Error Explanations

JSLint will hurt your feelings. It's time to make them better!

Don't make functions within a loop

When do I get this error?

JSLint and JSHint will throw the "Don't make functions within a loop" error when they encounter a function statement or expression within a for, while or do statement. 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:

Why do I get this error?

This error is raised to highlight a piece of code that may not work as you expect it to and could also indicate a 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.

The fundamental problem here is that the JavaScript interpreter will create an instance of the 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.

In the example above, when you click on one of the affected elements and trigger the event handler, the content will change to the final value of i. If there are 4 elements in the NodeList referred to by elems, the content of each element will end up being "4".

To work around this, we need to capture the value of i at each iteration of the loop and ensure that it's that value that is referred to by the click event handler bound at this iteration. A common solution is to wrap the body of the loop in an immediately invoked function expression (IIFE), creating a closure that captures the value of the variable:

This will work as we expect it to, with each element getting the correct value of i, but it's definitely starting to look messy and becoming harder to read (and therefore harder to maintain). And in any case, since there's still a function within the loop, JSLint and JSHint will still complain. To fix the issue, we need to move the function out of the loop, and maintain the closure:

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.

James Allardice

This article was written by James Allardice, an enthusiastic young JavaScript developer at Global Personals (we're looking for developers so please apply). He is passionate about writing clean, maintainable JavaScript and uses JSHint every day to help achieve this.

You can follow him on Twitter, fork him on GitHub and find him on Google+.

Proceeds generated by this site are donated to help advance other open source projects

comments powered by Disqus