The real WTF is (0, eval)('this')
wtf is that syntax??!!one!
The real WTF is (0, eval)('this')
wtf is that syntax??!!one!
calling a method or function directly (when in the global scope) will set `this` to the global object. But calling a method or bound function could have a different `this`, and calling a function directly in another context can have a different `this`.
the `(0, funcName)` syntax works by evaluating each item in the parens, but returns the last item. (don't ask me why this is in the syntax, I genuinely don't know and have never seen it used beyond this as far as I know)
So that syntax is abused to basically (simplified here) reassign the funcName to strip out the `this` that is bound to it and reassign it to the global context.
It then evals that `this`, and returns it! Meaning it will always get the global `this`, or `globalThis`!
It would be similar to doing this:
var thing = eval
thing('this')This is just how the comma operator works in other languages such as C and C++: https://en.m.wikipedia.org/wiki/Comma_operator
It just seems so foreign and out of place when used outside of those instances though, and for me at least the purpose of it wasn't intuitive at all!
If somebody rebound eval to redefine the 'this' inside - e.g., eval = (function(){myThis = ... ; return function(a){eval.apply(mythis, [a]);};})();
then calling eval with (0, eval)('this') will still not have rebinded the 'this' inside eval right? So why not just directly call eval('this')? Or am i missing the point?
I believe it is because of a weird distinction between "direct" and "indirect" calls in javascript. The spec says that an indirect call is guaranteed to execute in the global context, but a direct call will execute in whatever context it's in.
The `(0, eval)` makes it an indirect call by evaluating an expression that returns the function.
I'm not quite sure about the details of why indirect calls are treated that way though...
> (...) any invocation of eval that is not a direct call uses the global environment as its variable environment rather than the caller’s variable environment.
The `(0, eval)` makes it an indirect call by evaluating an expression that returns the function.
This is really timely. I just ran into an issue this weekend where I tried to generalize a function call like this (unaware of the direct vs. indirect semantics), and TypeScript yelled at me about it. Looks like it was trying to evaluate it in the global context, so the error makes sense now.