1

I been trying to understand this behavior of functions, but I couldn't find the answer.

I was trying to invoke each function of an array of functions. Everything worked fine, but when I put 'prompt' in the array, I got an error:

Uncaught TypeError: Illegal invocation.

To reproduce the error you can try:

[prompt][0]()

This code will work, I can't explain why neither:

[function() { return prompt }][0]()()

I know there are a few ways around this to make it work, but I want to understand what's is going on.

Thanks a lot!

atralice
  • 37
  • 5

2 Answers2

4

For background, see How does the “this” keyword work?.

The prompt function requires that this be window, which it would be if you called window.prompt() or (because window is the default context) prompt().

However, when you call [prompt][0](), this is the array object.

So the error is not because it is in an array, but because it isn't being called in the context of window.

You could pass the context explicitly:

[prompt][0].apply(window)
Community
  • 1
  • 1
Quentin
  • 800,325
  • 104
  • 1,079
  • 1,205
  • 1
    You could also use `bind` on prompt beforehand like this: `[prompt.bind(window)][0]()` – Jonathan Gray May 12 '16 at 12:32
  • A side note on "apply" and "bind": they're pretty weird at first; at least that was the case for me. Don't be discouraged if you don't completely understand it. I don't think a lot of people who code javascript daily fully understand "bind". – Thach Mai May 12 '16 at 12:33
  • I would also like to point out that since `apply` isn't being passed an array of arguments, `call` should be used instead. – Jonathan Gray May 12 '16 at 12:37
  • @JonathanGray — Why? Aren't they entirely interchangeable if you only pass one argument? – Quentin May 12 '16 at 12:44
  • @Quentin Technically, yes, but `apply` should really only be used in cases where `call` cannot. The former is for when you have unknown arguments in an array and the latter is for when you already explicitly know the arguments. Also if the OP needs to add arguments to the call, the way to do so wouldn't be as obvious using `apply`. – Jonathan Gray May 12 '16 at 12:47
2

Actually prompt is a native function, And it expects the this inside of it has to be window, But when you are extracting it from an array and calling it would make the this inside of it as the storage array object. Hence it is illegal and error is appearing.

A sample for you to understand,

function test(x){ 
 console.log(this === x) 
}

var x = [test];
x[0](x); //true

So from the above code you can understood the this inside of function which was extracted out from an array will point the array itself.

There are lot of work around for this, but a most readable one as per my opinion would be using call.

[prompt][0].call(window) //`this` object of prompt in this would be window.
Rajaprabhu Aravindasamy
  • 63,064
  • 13
  • 90
  • 119