JavaScript remove an IIFE event listener

I’m trying to remove click events from a list of id’s after adding them with an IIFE like this

function setupPlayer(player){
  var squareState = {};
  for (i = 0; i < allSquares.length; i++) {
      if(allSquares[i].innerHTML === "") {
        // set up a click event for each square
         document.getElementById(allSquares[i].getAttribute('id')).addEventListener('click', (clickSquare)(i));
      }
    }
}

The clickSquare function returns

function clickSquare(i){
  var num = i;
  return function() {
      document.getElementById(allSquares[num].getAttribute('id')).innerHTML=player;
  }
}

Then I try to remove them with

function removeClickEvents(){
  for (let i = 0; i < allSquares.length; i++) {
    document.getElementById(allSquares[i].getAttribute('id')).removeEventListener('click', clickSquare);
  }
} 

I’ve tried naming the returned anonymous function and using removeEventListener on that to no avail.

Answer

To remove event listener from a DOM element you need to pass the same function you used while adding event listener, as the parameter.

In javascript when you create an object it creates a new instance of that object class, so it won’t be equal to another object even if it is created with same parameters

Example:

{} != {} // returns true
[] != [] // returns true

Same goes with function, whenever you write function (){} it creates a new instance of Function class.

Example:

function a() {
    return function b() {}
}
a() != a() // returns true

Solution:

So for you to be able to remove the event listeners, you will have to store the functions you have passed to addEventListener

var listeners = [];

function setupPlayer(player) {
    var squareState = {};
    for (i = 0; i < allSquares.length; i++) {
        if(allSquares[i].innerHTML === "") {
            listeners[i] = clickSquare(i);
            document.getElementById(allSquares[i].getAttribute('id')).addEventListener('click', listeners[i]);
        }
    }
}

function clickSquare(i) {
    var num = i;
    return function() {
        document.getElementById(allSquares[num].getAttribute('id')).innerHTML=player;
    }
}

function removeClickEvents() {
    for (let i = 0; i < allSquares.length; i++) {
        if(listeners[i]) {
            document.getElementById(allSquares[i].getAttribute('id')).removeEventListener('click', listeners[i]);
        }
    }
}

From your code where you are using

document.getElementById(allSquares[i].getAttribute('id'))

I am assuming that allSquares[i] is a DOM element already, your code can be more simplified

var listeners = [];

function setupPlayer(player) {
    var squareState = {};
    for (i = 0; i < allSquares.length; i++) {
        if(allSquares[i].innerHTML === "") {
            listeners[i] = clickSquare(i);
            allSquares[i].addEventListener('click', listeners[i]);
        }
    }
}

function clickSquare(i) {
    var num = i;
    return function() {
        allSquares[num].innerHTML=player;
    }
}

function removeClickEvents() {
    for (let i = 0; i < allSquares.length; i++) {
        if(listeners[i]) {
            allSquares[i].removeEventListener('click', listeners[i]);
        }
    }
}