If the outer (function (i)
) function was removed then all the setTimeouts would use the same i
because a new i
(from the function parameter) would not be introduced (and it would lead to problems like this). As such the "hint" cannot be eliminated by simply removing it the outer anonymous function without changing other code as well. (Also see How do JavaScript closures work?)
While I disagree with this "hint" in general (and several other recommendations JSLint has), here are several different methods in which the "hint" can be avoided in this particular case besides merely disabling/ignoring the "hint".
One way to avoid the warning is to use setInterval
once and using only a single callback function. The iteration (over i'th/the-point) is then advanced inside the callback inside and clearInterval
is used when done. Note that the intent here is not to "improve performance" or eliminate the "hint" but show an alternative approach that some may perfer or find cleaner.
function addPins (map, pinLatLong, infoWindows) {
// In separate function so these variables are guaranteed to be
// in a new function scope.
var i = 0;
var timer = setTimeout(function() {
if (i == pinLatLng.length) {
clearTimeout(timer);
timer = null;
return;
}
var latLng = pinLatLong[i]; // only use `i` here
var latlong_array = latlong.lat_long.split(','),
// If combining `var` statements, which is another hint I disagree with,
// consider NOT using a previously introduced var's value immediately as it
// makes it harder to see the introduction (of latlong_array in this case).
marker = new google.maps.Marker({
position: new google.maps.LatLng(latlong_array[0],latlong_array[1]),
map: map,
animation: google.maps.Animation.DROP,
icon: pinimage,
optimized: false
});
// info windows
var infowindow = new google.maps.InfoWindow({
content: latlong.title,
maxWidth: 300
});
infoWindows.push(infowindow);
// Eliminated use of extra uneeded closure as all the variables
// used are contained within the callback's function context.
google.maps.event.addListener(marker, 'click', return function() {
infoWindow.open(map, this);
});
i++;
}, 250);
}
As a bonus it avoids the "hint" which I personally disagree with in general cases. Go ahead, create hundreds of function-objects: JavaScript code does this all the time.
A second way is to use the support setTimeout
has for additional arguments that it will supply as callback parameters. Thus the code could also be modified as so without the extra function (i)
that was causing the "hint" warning. While this does create many timeouts (as in the original) it only uses a single function for the callback and avoids the extra closures.
function showPin (i) {
// Everything that was in the setTimeout callback
// ..
}
for (var i = 0; i + 1 <= pinlatlong.length; i++) {
setTimeout(showPin, 250, i);
}
Another way is to trick by creating the closure in another function, which effectively does the same thing as the original code. Arguably this is cleaner and easier to read than the original, even if not trying to eliminate the "hint" per-se.
function mkShowPin (i) {
return function () {
// Everything that was in the setTimeout callback
// ..
}
}
for (var i = 0; i + 1 <= pinlatlong.length; i++) {
setTimeout(mkShowPin(i), 250);
}