I came across some code here where the Function constructor is called in an interesting way:
var jscriptVersion; // ...some code
jscriptVersion = new Function("/*@cc_on return @_jscript_version; @*/")();
At first I thought the extra parentheses were a mistake but after testing a bit in the console I thought maybe it was a shortcut to get a return value:
var a = new Function("return 'abc'");
var b = new Function("");
var c = new Function("")();
var d = new Function("return 'xyz'")();
console.log(a, typeof a); // f anonymous() { return 'abc' } , function
console.log(b, typeof b); // f anonymous() { } , function
console.log(c, typeof c); // undefined , undefined
console.log(d, typeof d); // xyz , string
I'm guessing d
is (almost, aside from the new
keyword) functionally identical to:
var d2 = function() { return 'xyz' }(); console.log(d2); // xyz
But again I've literally never seen trailing parentheses after a function expression that is not an IIFE, and I'm surprised that the code defining d2
doesn't result in a SyntaxError.
I looked at MDN but couldn't find clear information on how this would be used.
And is this valid JS or does implementation of double parentheses vary across browsers?
The trailing parentheses after new Function
will immediately invoke the function. It's basically the same thing as an IIFE, except that the function that is called is dynamically constructed from the passed string - new Function
returns a function, which is then immediately run if followed by ()
.
var a = new Function("return 'abc'");
var b = new Function("");
var c = new Function("")();
var d = new Function("return 'xyz'")();
console.log(a, typeof a); // f anonymous() { return 'abc' } , function
// because that is the function that was constructed from the `return 'abc'` string
console.log(b, typeof b); // f anonymous() { } , function
// because the string passed was empty, so the function returned from new Function is empty
console.log(c, typeof c); // undefined , undefined
// because an empty function, when invoked, does not return anything:
// x = (() => {
// })();
// x is undefined
console.log(d, typeof d); // xyz , string
// because the constructed function's body returns the `xyz` string
// and the constructed function was invoked immediately
Any function that returns a function can have ()
after its invocation, not just new Function
or an IIFE. For example:
const makeFn = arg => () => console.log(arg);
const fnThatLogs3 = makeFn(3);
fnThatLogs3();
makeFn(4)();