The answer is quite simple...
The module wrapper
Recalling...
The undefined
is a property of the object global
, that is, it is a variable in the global scope. The initial value of undefined
is the primitive value undefined
.
In modern browsers, the Ecmascript 5 specification defines the undefined
is a not configurable read-only property. Even when this is not the case, avoid overwriting it.
Since undefined
is not a reserved word, it can be used as an identifier (variable name) in any scope that is not the global scope.
source
Example of code running outside the global scope:
;// escreve no console "foo string"
(function () {
var undefined = 'foo'
console.log(undefined, typeof undefined)
})()
// escreve no console "foo string"
;(function (undefined) {
console.log(undefined, typeof undefined)
})('foo')
Yeah, but what about Node.js?
That’s where the module wrapper. Each JS file (module) that will be executed by Node.js, undergoes, before it is executed, a "packaging" of scope that is caused by a function. This, in addition to causing a closed scope in the module, causes this file does not run in global scope. This behavior also explains the question of this
in Node.js, which was addressed in this question...
In Nodejs, declaring any variable outside the scope of any function, links it only to the scope of the module itself (not to the global object). Each file has its own scope, this was thought to prevent a variable from extrapolating the scope of a file...
Then, when executing the question code in Node.js, the function looks like this "below the board" because of the module wrapper:
(function (exports, require, module, __filename, __dirname) {
'use strict'
var undefined = { foo: 'bar' }
console.log(undefined)
})
If you simulate this execution in the browser, we will have no error:
(function (exports, require, module, __filename, __dirname) {
'use strict'
var undefined = { foo: 'bar' }
console.log(undefined)
})()
Concluding
As much as you don’t use a function in your file, Node.js bundles all your code within a function. This is due to the characteristic issues of Plataform, in order to maintain some things' behavior:
- It keeps the variables top-level (defined with
var
, const
or let
) with scope in the module instead of the global object, thus allowing working with attributes that will be private within each file, where these attributes can only be accessed by functions within the file itself.
- File attributes will only be accessed by other files if they are explicitly exported.
- This helps to provide some global looking variables that are really specific to the module, such as:
- The objects
module
and exports
that the deployer can use to export module values.
- The variables of convenience
__filename
and __dirname
, containing the absolute filename of the module and the directory path.
OBS:
The explanation of the above conclusion is valid if one considers the type
as commonjs
. In the case of the type module
, the parameters are not applicable to the module wrapper.
OBS 2:
The same behavior applies to the NaN
, because it is also a property of the global object and is not a keyword of the JS:
(function (exports, require, module, __filename, __dirname) {
'use strict'
var NaN = { foo: 'bar' }
console.log(NaN)
})()
In the strict way:
'use strict';
var NaN = {
foo: 'bar'
}
console.log(NaN)
Out of the strict way:
var NaN = {
foo: 'bar'
}
console.log(NaN)
console.log(Object.getOwnPropertyDescriptor(globalThis, 'NaN'))
Good answer (and question)! But what is this bizarre place semicolon before the IIFE? Isn’t it better to simply use the semicolon at the end of each statement where expected? : D
– Luiz Felipe
@Luizfelipe kkkkkkkkkkkkkk, I just have an explanation for this:
SHIFT
+ALT
+F
.– Cmte Cardeal