Calling a function in this roundabout way:
(throwAwayValueHere, fn)(args);
works like this:
- The comma expression
throwAwayValueHere, fn
is evaluated: The comma operator evaluates its first operand, throws away that value, then evaluates its second operand and takes that value as its result.
- That value is then called as a function, passing in the arguments.
Doing the call that way has an effect in two situations:
1. If the function is on an object property, e.g.:
(throwAwayValueHere, obj.fn)(args);
it calls the function without setting this
to obj
during the function call; instead, it's set to the default, either the global this
value (window
on browsers) or undefined
in strict mode.
Example:
"use strict";
const obj = {
value: 42,
fn: function() {
console.log(`typeof this = ${typeof this}`);
if (typeof this === "object") {
console.log(`this.value = ${this.value}`);
}
}
};
// Normal call:
console.log(`obj.fn():`);
obj.fn();
// Indirect call:
console.log(`(0, obj.fn)():`);
(0, obj.fn)();
This is the reason Babel is doing it there: In the original code, the call was simply a()
, which calls a
with the default this
value. Doing (0, _b.a)()
does the same thing even though a
is a property of _b
.
2. If the function is eval
, it makes it an indirect eval
which means it's evaluated as though at global scope, rather than eval
's default behavior of running arbitrary code from a string in local scope, giving it access to all in-scope variables.
Example:
"use strict";
let a = "global a";
function directEval() {
let a = "local a";
eval("console.log(`a = ${a}`);");
}
function indirectEval() {
let a = "local a";
(0,eval)("console.log(`a = ${a}`);");
}
console.log("direct:");
directEval();
console.log("indirect:");
indirectEval();