Why you cannot pass location.reload as an argument

Ansh Saini - Apr 17 '22 - - Dev Community

Let's say we have a function named blockUser which looks something like this

const blockUser = (afterBlock = window.location.reload) => {
  // Some code to block the user
  afterBlock()
}
Enter fullscreen mode Exit fullscreen mode

The interesting thing about this function is the afterBlock argument which defaults to window.location.reload. We basically want to reload the page after a user is blocked. But not always. Hence, the argument.

Lets use our pretty function:

blockUser()
Enter fullscreen mode Exit fullscreen mode

Oops

Illegal Invocation Error from Chrome
Firefox gives us a more descriptive error.
Illegal Invocation Error from Firefox

Why does this happen?

location.reload requires that this should point to location. When we are using javascript functions, this is bound to the scope from which the function was called.
if we call window.location.reload() directly, then the reload function is getting called through the location object. But lets say we do:

const test = window.location.reload
test()
Enter fullscreen mode Exit fullscreen mode

Illegal Invocation Error from Chrome

We will still get the same error.
Let's try to create our own reload function to see what's going on.

const fakeWindow = { location: { reload: function() { console.log(this) } } }
fakeWindow.location.reload()

// Re-assigning
let test = fakeWindow.location.reload
test()
Enter fullscreen mode Exit fullscreen mode

Custom reload function

Whoa, looks like this is not the same anymore when we assign the reload function to a variable. If you remember the Firefox error, the reload function requires that it should be called from the context of Location. When we assign it to a variable, it gets called from the context of Window.

How can we fix it?

The fix is pretty simple, you can just wrap a function around your re-assignment.

const blockUser = (afterBlock = () => window.location.reload()) => {
  // Some code to block the user
  afterBlock()
}
const test = () => window.location.reload()
Enter fullscreen mode Exit fullscreen mode

It works now! 😄

Bonus

Can you guess what will happen if we defined our fakeWindow object a little differently?

const fakeWindow = { location: { reload: () => { console.log(this) } } }
fakeWindow.location.reload()
Enter fullscreen mode Exit fullscreen mode

Have you ever come across this problem in a real project? Drop your thoughts and experiences in the comments. Don't forget to answer the question in Bonus section :)

. . . . . . . . . . .