Intro
The global object is considered a problem that Javascript cannot get rid of due to backward compatibility. Every developer knows the headache of trying to create/modify/remove some Javascript functionality without breaking any code that makes use of this functionality. In addition, the global object negatively affects the response as demonstrated in this my answer, at least in the browsers.
Ecmascript implemented some features to make it easier to avoid unintentional use of the object global. const
and let
, for example, they do not create properties on the global object. In addition to in Node.js, each module (script file) has its own scope to avoid affecting the global Node.js. Think of the scope that all the code of the module (file) is within a function.
History
Historically, accessing the global object with Javascript requires a different syntax according to the Javascript code execution environment.
- In browsers, we can access the global object using
window
, self
or frames
console.log(window);
console.log(self);
console.log(frames);
Even if we make a comparison, we can see that window
and frames
has the same pointer in memory:
console.log(window === frames); // true
self
only works in the context of Web Workers.
- In Node.js, none of the above works. You should use
global
:
$ node
Welcome to Node.js v14.15.0.
Type ".help" for more information.
> console.log(global)
// imprime:
// <ref *1> Object [global] {
// global: [Circular *1],
// clearInterval: [Function: clearInterval],
// clearTimeout: [Function: clearTimeout],
// setInterval: [Function: setInterval],
// setTimeout: [Function: setTimeout] {
// [Symbol(nodejs.util.promisify.custom)]: [Function (anonymous)]
// },
// queueMicrotask: [Function: queueMicrotask],
// clearImmediate: [Function: clearImmediate],
// setImmediate: [Function: setImmediate] {
// [Symbol(nodejs.util.promisify.custom)]: [Function (anonymous)]
// }
// }
// undefined
// >
It is possible to access the global object through the this
in a function without the use of 'use strict'
, but we know the problems that this can generate.
(function() {
console.log(this); // => Window {...}
})();
(() => {
console.log(this); // => Window {...}
})();
(function() {
'use strict';
console.log(this); // => undefined
})();
Before the introduction of globalThis
, we had two ways to return the global object:
- Use of the
Function('return this')()
:
console.log(Function('return this')());
But this form was not the most appropriate, because it generated problems of Content Security Policy.
- Use of a custom function. Let’s do an example where we want to know if the
setTimeout
, for example, it is present in the execution environment. Making a if
, we have the code:
var getGlobal = function() {
if (typeof self !== 'undefined') {
return self;
}
if (typeof window !== 'undefined') {
return window;
}
if (typeof global !== 'undefined') {
return global;
}
throw new Error('unable to locate global object');
};
var globals = getGlobal();
if (typeof globals.setTimeout !== 'function') {
// setTimeout não está presente nesse ambiente
}
Let’s face it, it’s a lot of code to do something simple.
Currently
With the introduction of globalThis
, he is responsible for making a resolve from the context of the Javascript code execution environment and return the global object corresponding to the execution environment. The use of the functions mentioned in 1
and 2
are no longer needed and the code would be much simpler:
if (typeof globalThis.setTimeout !== 'function') {
// setTimeout não está presente nesse ambiente
}
Usefulness
Where the use of globalThis
would be welcome:
For example, a polyfill can be used to mimic the functionality of an HTML Canvas element in Microsoft Internet Explorer 7, using a Silverlight plugin, or imitate drive support rem
CSS or text-shadow
; or whatever you want.
- I never implemented this example, but it worked. Let’s assume you want to create a function
digaOla
and you want to be able to use it in every environment you run Javascript code. You have the same application adapted to work on your browser, mobile devices, desktop, Iot (why not?) and the soul of the application is in your Node.js server. How to reuse the same function digaOla
across the execution context on each platform? Using globalThis
and not worrying about writing gigantic codes to support different contexts, checking and testing.
Using in the browser:
if (!globalThis.digaOla) {
console.log('Posso criar minha função!');
globalThis.digaOla = function () {
return 'Olá :)';
};
} else {
console.log('Não posso criar minha função!');
}
console.log('Dizendo olá: ', globalThis.digaOla());
How it could be reused and used in Node.js:
Archives:
|
\_ test.js
|
\_ test2.js
test2.js:
module.exports = {
test: () => {
console.log('De dentro do arquivo test_copy.js: ', globalThis.digaOla());
}
};
test js.:
if (!globalThis.digaOla) {
console.log('Posso criar minha função!');
globalThis.digaOla = function () {
return 'Olá :)';
};
} else {
console.log('Não posso criar minha função!');
}
console.log('Dizendo olá: ', globalThis.digaOla());
const { test } = require('./test2');
test();
Running node test.js
:
$ node test.js
Posso criar minha função!
Dizendo olá: Olá :)
Dizendo olá de dentro do arquivo test_copy.js: Olá :)
Links:
Related, but it’s worth a full answer
– Cmte Cardeal
interesting @Cmtecardeal humm, by name suggests something like a this "global", but it is replacing the
window
, from what I saw in the question is something like alias, but "multiplatform," that would be?– Ricardo Pontual
Exactly. He makes a resolve of the global object according to the JS code execution platform.
– Cmte Cardeal
cool, post an answer with this to document better :)
– Ricardo Pontual