location.reload in addEventListener

Chooi J. Q. picture Chooi J. Q. · Mar 31, 2018 · Viewed 8.1k times · Source

I'm trying to make the document reload when a button is clicked. Here's my code:

var e = document.getElementById('a');
e.addEventListener('click',location.reload);

It returns Uncaught TypeError: Illegal Invocation after e was clicked. However, the following code works and the document reloaded:

var e = document.getElementById('a');//same thing
e.addEventListener('click',function(){location.reload()});
//warp location.reload inside function -> works!

I don't understand why the first code doesn't work. Can anyone give some explanation? Thanks!

Answer

Andrew Svietlichnyy picture Andrew Svietlichnyy · Mar 31, 2018

When you are calling location.reload() it not only calls function, but also sets this to the value of location, so these two are equivalent:

location.reload();
location.reload.call(location);

However, when you supply it to addEventListener only function reference is stored, but not the value of this, so when it's called it's equivalent to

location.reload.call(undefined); // strict mode
location.reload.call(window); // sloppy mode

For example Firefox provides a more clear error message: TypeError: 'reload' called on an object that does not implement interface Location.

As such for proper behavior you need to create a closure, or bind this to location, so both will work:

e.addEventListener('click', function(){location.reload()});
e.addEventListener('click', location.reload.bind(location));