-1

This is a code to control my character. "control" is a name of button class. Im using for loop to declare adding touch event listener. I had could change the color while its on touch. element on index 0 is for turn left, element on index 1 is for jump.

problem : when i check the number of i variable with console log in touch event function, its return 15. I only had 4 element. 15 was not match on my cases.

My question is how the i variable returns 15?

var getControl = {
    buts : document.getElementsByClassName("control"),

    build : function(world){
        for(i = 0; i < 4; i++){

            this.buts[i].addEventListener("touchstart",function(e){
                console.log(getControl.temp);
                e.preventDefault();
                this.style.backgroundColor = "green";
                console.log(i);
                switch(i){
                    case 0:
                        misc[0].left();
                        console.log("left");
                        break;
                    case 1:
                        misc[0].jump();
                        break;
                    case 2:
                        misc[0].right();
                        break;
                    case 3:

                        break;
                };
            },false);
            this.buts[i].addEventListener("touchend",function(e){
                e.preventDefault();
                this.style.backgroundColor = "red";
            },false);
            this.buts[i].addEventListener("touchleave",function(e){
                e.preventDefault();
                this.style.backgroundColor = "red";
            },false);
Alif
  • 57
  • 1
  • 8

2 Answers2

1
  1. First of all for(i = 0; i < 4; i++) will declare i as global variable, so (assuming that you're doing that for all the loops in your code) i will have the value it got from the last executed for loop.

What you should do, for all the for loops in this code and future ones, is to declare the index i (or j or ...) like this:

for(var i = 0; i < 4; i++) {
  1. for loops will have the same scope throughout the whole iterations, so the closure will be messed up. Because all the event listeners will get a reference to the same i, so when they will get called they will try and see what value i have (even if you correct the problem 1., i will not have the value you expect because it will be changed after the reference to it was passed to the event listener. for changed it by continually incrementing it). What you need is a mechanism to create unique scopes for each item of the array. You can try this solution, or use an alternative to for like forEach (which is more or less similar to the solution in the link).

So this:

for(i = 0; i < 4; i++) {
    this.buts[i].addEventListener("touchstart", function(e) {
        // ...

should be replaced by this:

// since buts is an array-like object we can't use forEach directly but we could call it like this
Array.prototype.forEach.call(this.buts, function(but, i) {
    but.addEventListener("touchstart", function(e) {
        // you can use i here and it will work
    });
    // ...
    // but is equivalent to this.buts[i]
});
Community
  • 1
  • 1
ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73
  • I had change the `i` into `j` and its return 4. Then on `this.buts[i].forEach(function(but, i) {` says that forEach is not a function. – Alif Feb 09 '17 at 13:21
  • @Alif I've just noticed that `buts` is not an array. (`document.getElementsByClassName`) return an **array-like** object not an **array**. I updated my answer, now it should work! – ibrahim mahrir Feb 09 '17 at 13:33
0

In your for loop you have

i=0

This declares i as a global variable, so it is probably being incremented or assigned somewhere else. The global namespace is dangerous.

Try making a variable in your function's scope like this:

var i = 0
jake smith
  • 66
  • 1
  • 3