3

I want to override a function already attached to an event. Like that :

let orFn = () => {
  console.log('old');
};

buttonEl.addEventListener('click', orFn);

orFn = () => {
  console.log('new');
};

However, when I click on the button, the old function is still called. I have seen this stackoverflow. I can't use a function wrapper in my case. And I want to understand why this is not working.

My code is available for testing here: jsfiddle.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
MarcF.
  • 31
  • 2
  • 3
    It's not working because you set a reference to a function. Just because you redefined the reference later doesn't mean the reference captured by `addEventListener` changed. The old function doesn't magically disappear. You can *remove* a handler and add a new one. – Dave Newton Mar 10 '20 at 16:08
  • so the old reference binds to the addEventListener and there is now way to change it? – EugenSunic Mar 10 '20 at 16:19
  • 2
    Redefining a reference doesn't change its value elsewhere--it's like writing `let foo = () => "bar"; let bar = foo; foo = () => "plugh";` `bar` gets a reference to `foo`'s value at the time `bar` is defined. Changing `foo` has zero effect on `bar`'s reference. You can remove the handler and add a new one. You can keep the old one and add a new one. You can wrap `addEventListener` and do whatever you want. But JS semantics are JS semantics. – Dave Newton Mar 10 '20 at 16:32
  • @DaveNewton thanks. It's so clear now. – MarcF. Mar 11 '20 at 10:00

2 Answers2

1

One way is to remove first listener, then add another one

let orFn = () => {
  console.log('old');
};

let orFnNew = () => {
  console.log('new');
};

var buttonEl = document.querySelector('button')

buttonEl.addEventListener('click', orFn);

// remove old listener
buttonEl.removeEventListener('click', orFn);

// add another one
buttonEl.addEventListener('click', orFnNew);
<button>button</button>

Another way is to have one listener, that may call different functions inside. Example:

// button
const buttonEl = document.querySelector('button')

const orFn = () => {
  console.log('old');
};

const orFnNew = () => {
  console.log('new');
};

// function that will be called
let functionToCall = orFn;

buttonEl.addEventListener('click', (event) => { // single listener
  
  functionToCall.call(event); // call a function with event


  functionToCall = functionToCall === orFn ? orFnNew : orFn; // change function to be called
});
<button>button</button>
qiAlex
  • 4,290
  • 2
  • 19
  • 35
0

One way of using bind().

const btn = document.getElementById('btn');

let orFn = () => {
  alert('old');
};

orFn = () => {
  alert('new');
};

orFn.bind(orFn)

btn.addEventListener('click', orFn);

This will bind with new function and show new in alert Popup.

Puneet Sharma
  • 305
  • 3
  • 14