Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what's the purpose of `new Function("return this")()` in immediately invoked function

Tags:

javascript

I'm reviewing the setImmediate polyfill and it's wrapped inside immediate-invoking function with the following:

(function (global, undefined) {
    "use strict";
...
}(new Function("return this")()));

I'm confused about the purpose the last statement and the parameters being passed to the function. Does it have something to do that this code might be run inside a browser as well as on Node.js? Can you please clarify?

like image 482
Max Koretskyi Avatar asked Apr 17 '15 17:04

Max Koretskyi


People also ask

Why use immediately invoked function expression?

An Immediately-invoked Function Expression (IIFE for friends) is a way to execute functions immediately, as soon as they are created. IIFEs are very useful because they don't pollute the global object, and they are a simple way to isolate variables declarations.

What is the use of new function?

It is used in very specific cases, like when we receive code from a server, or to dynamically compile a function from a template, in complex web-applications.

What does IIFE mean in JavaScript?

An IIFE (Immediately Invoked Function Expression) is a JavaScript function that runs as soon as it is defined.

What is function () () in JavaScript?

A function in JavaScript is similar to a procedure—a set of statements that performs a task or calculates a value, but for a procedure to qualify as a function, it should take some input and return an output where there is some obvious relationship between the input and the output.


2 Answers

The code is written so it has access to the global scope, without having to know what the object containing that scope is. For instance in a browser the global scope is window, but in other containers that is not the case.

By using the Function constructor, you get direct access to the global scope:

Note: Functions created with the Function constructor do not create closures to their creation contexts; they always are created in the global scope. When running them, they will only be able to access their own local variables and global ones, not the ones from the scope in which the Function constructor was called. This is different from using eval with code for a function expression.

So by doing:

(new Function("return this")())

You create and invoke a new function on the global scope, that returns whatever that global scope is. This is then immediately passed to the main function as the global object.

like image 177
James Thorpe Avatar answered Sep 27 '22 10:09

James Thorpe


In non-strict mode, when a function is called without setting the this value, it will become the global object:

10.4.3 Entering Function Code

  1. If the function code is strict code, set the ThisBinding to thisArg.
  2. Else if thisArg is null or undefined, set the ThisBinding to the global object.

Therefore, the this keyword may be way to obtain a reference to the global object:

this; // the global object

The first problem is that this could have been customized (e.g. with apply or call):

(function() {
    this; // `123`, not the global object!
}).call(123);

This can be easily fixed using a self-executing function:

// `this` may not be the global object here
(function() {
    this; // the global object
})();

But there is a more serious problem: this doesn't become the global object in strict mode:

'use strict';
(function() {
    this; // `undefined`, not the global object!
})();

To fix that, you can use a Function Constructor. Even inside strict mode, the new function will be non-strict by default.

'use strict';
(function() {
    new Function("return this")(); // the global object
})();
like image 26
Oriol Avatar answered Sep 29 '22 10:09

Oriol