John Cooper
John Cooper

Reputation: 7621

Scope Issue in JavaScript - Cannot Call add of Undefined...

When i say...

table[i].add(deleteButton) // this works...

// When i call inside an event listener... it's says cannot call add of undefined.

imageLogo.addEventListener('click', function (e) {
        table[i].add(deleteButton);
    } else {
        imageLogo.backgroundImage = '/images/markHorizontal.png';
        table[i].remove(deleteButton);
    }
});

Upvotes: 0

Views: 117

Answers (2)

user113716
user113716

Reputation: 322452

You've excluded some important code, but I'll assume you're in a for loop.

If so, the issue is that each click handler you're creating in the loop is referencing the same i variable. This is because JavaScript (currently) does not have block scope. Only function scope.

You need to create a new variable scope for each i value in the loop that you want to persist.

function add_listener( i ) {
    imageLogo.addEventListener('click', function (e) {
            table[i].add(deleteButton);
        } else {
            imageLogo.backgroundImage = '/images/markHorizontal.png';
            table[i].remove(deleteButton);
        }
    });
}

for( var i = 0; i < table.length; i++ ) {

    add_listener( i );

}

By invoking a function in the loop, you've created a new variable scope. Because you passed i to that function, and created your handler in that function, the i that the function references is local to that scope, and will persist.

So when the handler is invoked, it is referring to the i that was created in the same variable scope where that particular handler was created.


There are other variations on the same concept. For example, you could have the function return a function to be used as the handler.

function make_listener( i ) {
    return function (e) {
            table[i].add(deleteButton);
        } else {
            imageLogo.backgroundImage = '/images/markHorizontal.png';
            table[i].remove(deleteButton);
        }
    };
}

for( var i = 0; i < table.length; i++ ) {

    imageLogo.addEventListener('click', make_listener( i ) );

}

Upvotes: 1

Tarek Fadel
Tarek Fadel

Reputation: 1959

If you haven't prefixed the declaration to table with var you can do window.table[i].add(deleteButton); since all variables not declared with a var are descendants of window

Upvotes: 2

Related Questions