Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Functions declared within loops referencing an outer scoped variable may lead to confusing semantics. What is wrong? [duplicate]

Tags:

javascript

Can someone tell me what is wrong with my code, especially the "Full screen event" part. Thanks!

JSLint says "Functions declared within loops referencing an outer scoped variable may lead to confusing semantics."

function initialize() {
    var mapProp = {
        center: new google.maps.LatLng(45.502808, -73.571486),
    };
    var map = [];
    map[0] = new google.maps.Map(document.getElementById("map1"), mapProp);
    map[1] = new google.maps.Map(document.getElementById("map2"), mapProp);
    map[2] = new google.maps.Map(document.getElementById("map3"), mapProp);

    new google.maps.Marker({
        position: new google.maps.LatLng(45.502808, -73.571486),
        map: map[0], title: 'Sunnyvale '
    });
    new google.maps.Marker({
        position: new google.maps.LatLng(45.502808, -73.571486),
        map: map[1], title: 'Sunnyvale '
    });
    new google.maps.Marker({
        position: new google.maps.LatLng(45.502808, -73.571486),
        map: map[2], title: 'Sunnyvale '
    });


    google.maps.event.addDomListener(window, "resize", function () {
        for (i = 0; i < 3; i++) {
            var center = map[i].getCenter();
            /*var bounds = map[i].getBounds();*/
            var zoom = map[i].getZoom();
            google.maps.event.trigger(map[i], "resize");
            /*map[i].fitBounds(bounds);*/
            map[i].setCenter(center);
            google.maps.event.addListenerOnce(map[i], 'bounds_changed', function(event) {
                this.setZoom(zoom);
            });
        }

    });

    /** Full Screen event */

    for (i = 0; i < 3; i++) {
        var centerChanged = [];
        var zoomChanged = [];
        google.maps.event.addListener(map[i], 'center_changed', function() {

            var centerChanged[i] = map[i].getCenter();
            var zoomChanged[i] = map[i].getZoom();
        });
        $(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange', function() {
            map[i].setCenter(centerChanged[i]);
            google.maps.event.addListenerOnce(map[i], 'bounds_changed', function (event) {
                this.setZoom(zoomChanged[i]);
            });
        });
    }

}
google.maps.event.addDomListener(window, 'load', initialize);

JSLint says "Functions declared within loops referencing an outer scoped variable may lead to confusing semantics."

like image 335
Emilio Avatar asked Sep 03 '17 19:09

Emilio


1 Answers

In your loop, i starts at 0 and iterates until it's equal to 3. That means that whenever you access i after the loop has finished running (for example, in a listener function) it will be equal to 3. You can see this in the following code:

for(var i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(i);
    }, 1000);
}

That will print all 5s because the function is being called after the loop has finished iterating.

Edit: To fix the issue, you can use javascript's hip new declaration statements: let and const. They exist only in the scope that they are declared, and their values are therefore not overwritten.

for(var i = 0; i < 5; i++) {
    const j = i;
    setTimeout(function() {
        console.log(j);
    }, 1000);
}

Edit 2: Replacing var i with let i appears to work as well:

for(let i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(i);
    }, 1000);
}

Edit 3: If es6 isn't an option, you could bind i's value to the function:

for(var i = 0; i < 5; i++) {
    setTimeout((function(j) {
        console.log(j);
    }).bind(null, i), 1000);
}
like image 160
EKW Avatar answered Sep 20 '22 21:09

EKW