简体   繁体   中英

Javascript array not using for loop variable

I have an array filled with strings that have the same name as Google Maps Polygon Objects I've created. I'd like to iterate through the array to set a specific option. Here's the code:

for (var i = 0; i < statesPoly.length; i++) {
    google.maps.event.addListener(statesPoly[i], 'mouseover', function() {
        statesPoly[i].setOptions({ strokeWeight: '2' });
    });
}

When executed I get "Cannot call method 'setOptions' of undefined" as the script seems to be using statesPoly[i] literally. When I replace statesPoly[i] with, for example, statesPoly[11], the script works as expected.

The loop also works as expected when I try something like this:

for (var i = 0; i < statesPoly.length; i++) {
    alert(statesPoly[i].strokeColor);
}

What am I doing wrong?

UPDATE:

Getting closer here. I believe the reason that using this works in some cases is because my function is expecting an object and I am giving it a string. Could this be the case?

alert(statesPoly[0]);
        google.maps.event.addListener(sarawakPoly, 'mouseover', function() {
            $("#"+statesPoly[0]).addClass("highlight");
            sarawakPoly.setOptions({ strokeWeight: '2' });
            //infowindow.open(map,marker);
        });

The code above will alert with SarawakPoly, and using statesPoly[0] as a string in the ID works as expected. This

 alert(statesPoly[0]);
        google.maps.event.addListener(statesPoly[0], 'mouseover', function() {
            $("#"+statesPoly[0]).addClass("highlight");
            statesPoly[0].setOptions({ strokeWeight: '2' });
            //infowindow.open(map,marker);
        });

Does not work because "Uncaught TypeError: Cannot read property 'mouseover' of undefined"

If I'm right, how to I get my JS to cast my array variable as an object?

This is a very common mistake in JavaScript code:

for (var i = 0; i < n; i++) {
    registerSomeCallback(function () {
        console.log(i);
    });
}

On each loop iteration the variable i is incremented, and becasue of JavaScript's lexical scoping the functions defined on each iteration share the same i variable. This means that when the callback is invoked (in your case when a Google Maps event occurs), i will always be the last value the loop reached.

It's as if you're doing this:

var i, fn;

i = 0;
fn = function () { alert(i); };
fn(); // will alert "0"
i = 1;
fn(); // i has changed, will now alert "1"
i = 2;
fn(); // i has changed again, will now alert "2"

You need to make sure there's a new variable scope for each iteration of your loop, for example:

for (var i = 0; i < n; i++) {
    (function (n) {
        registerSomeCallback(function () {
            console.log(n);
        });
    }(i));
}

In this version of the code, each callback is defined in its own variable scope with its own counter variable (which you could still call i , but I've called n to make the example more clear).

Can you try using this instead?

    for (var i = 0; i < statesPoly.length; i++) {
      (function(i) {
        google.maps.event.addListener(statesPoly[i], 'mouseover', function() {
            this.setOptions({ strokeWeight: '2' });
        });
       })(i);
    }

statesPoly[i] is undefined because your variable i is not defined inside the new function you attached to the event listener.

You can do several things here but the most simple way will be to pass this variable to the function. Something like that:

google.maps.event.addListener(statesPoly[i], 'mouseover', function(i) {
  statesPoly[i].setOptions({ strokeWeight: '2' });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM