diff --git a/1-js/06-advanced-functions/05-global-object/article.md b/1-js/06-advanced-functions/05-global-object/article.md index da4adc2b..a05157a5 100644 --- a/1-js/06-advanced-functions/05-global-object/article.md +++ b/1-js/06-advanced-functions/05-global-object/article.md @@ -1,11 +1,13 @@ # Global object -The global object provides variables and functions that are available anywhere. Mostly, the ones that are built into the language or the host environment. +The global object provides variables and functions that are available anywhere. Mostly, the ones that are built into the language or the environment. -In a browser it is named "window", for Node.js it is "global", for other environments it may have another name. +In a browser it is named `window`, for Node.js it is `global`, for other environments it may have another name. -For instance, we can call `alert` as a method of `window`: +Recently, `globalThis` was added to the language, as a standartized name for a global object, that should be supported across all environments. In some browsers, namely non-Chromium Edge, `globalThis` is not yet supported, but can be easily polyfilled. + +All properties of the global object can be accessed directly: ```js run alert("Hello"); @@ -14,142 +16,72 @@ alert("Hello"); window.alert("Hello"); ``` -We can reference other built-in functions like `Array` as `window.Array` and create our own properties on it. +In a browser, global variables declared with `var` become the property of the global object: -## Browser: the "window" object +```js run untrusted refresh +var gVar = 5; -For historical reasons, in-browser `window` object is a bit messed up. +alert(window.gVar); // 5 (became a property of the global object) +``` -1. It provides the "browser window" functionality, besides playing the role of a global object. +Please don't rely on that! This behavior exists for compatibility reasons. Modern scripts use JavaScript modules where such thing doesn't happen. We'll cover them later in the chapter [](info:modules). - We can use `window` to access properties and methods, specific to the browser window: +Also, more modern variable declarations `let` and `const` do not exhibit such behavior at all: - ```js run - alert(window.innerHeight); // shows the browser window height +```js run untrusted refresh +let gLet = 5; - window.open('http://google.com'); // opens a new browser window - ``` +alert(window.gLet); // undefined (doesn't become a property of the global object) +``` -2. Top-level `var` variables and function declarations automatically become properties of `window`. +If a value is so important that you'd like to make it available globally, write it directly as a property: - For instance: - ```js untrusted run no-strict refresh - var x = 5; +```js run +*!* +// make current user information global, to let all scripts access it +window.currentUser = { + name: "John" +}; +*/!* - alert(window.x); // 5 (var x becomes a property of window) +// somewhere else in code +alert(currentUser.name); // John - window.x = 0; +// or, if we have a local variable with the name "value" +// get it from window explicitly (safe!) +alert(window.currentUser.name); // John +``` - alert(x); // 0, variable modified - ``` +That said, using global variables is generally discouraged. There should be as few global variables as possible. The code design where a function gets "input" variables and produces certain "outcome" is clearer, less prone to errors and easier to test. - Please note, that doesn't happen with more modern `let/const` declarations: +## Using for polyfills - ```js untrusted run no-strict refresh - let x = 5; +We can test the global object for support of modern language features. - alert(window.x); // undefined ("let" doesn't create a window property) - ``` +For instance, test if a build-in `Promise` object exists (it doesn't in really old browsers): +```js run +if (!window.Promise) { + alert("Your browser is really old!"); +} +``` -3. Also, all scripts share the same global scope, so variables declared in one ` +```js run +if (!window.Promise) { + window.Promise = ... // custom implementation of the modern language feature +} +``` - - ``` +## Summary -4. And, a minor thing, but still: the value of `this` in the global scope is `window`. +- The global object holds variables that should be available everywhere. - ```js untrusted run no-strict refresh - alert(this); // window - ``` + That includes JavaScript built-ins, such as `Array` and environment-specific values, such as `window.innerHeight` -- the window height in the browser. +- The global object has a universal name `globalThis`. -Why was it made like this? At the time of the language creation, the idea to merge multiple aspects into a single `window` object was to "make things simple". But since then many things changed. Tiny scripts became big applications that require proper architecture. + ...But more often is referred by "old-school" environment-specific names, such as `window` (browser) and `global` (Node.js). As `globalThis` is a recent proposal, it's not supported in non-Chromium Edge (but can be polyfilled). +- We should store values in the global object only if they're truly global for our project. And keep their number at minimum. +- In-browser, unless we're using [modules](info:modules), a global variable declared with `var` becomes a property of the global object. -Is it good that different scripts (possibly from different sources) see variables of each other? - -No, it's not, because it may lead to naming conflicts: the same variable name can be used in two scripts for different purposes, so they will conflict with each other. - -As of now, the multi-purpose `window` is considered a design mistake in the language. - -Luckily, there's a "road out of hell", called "JavaScript modules". - -If we set `type="module"` attribute on a ` - ``` - -- Two modules that do not see variables of each other: - - ```html run - - - - ``` - -- And, the last minor thing, the top-level value of `this` in a module is `undefined` (why should it be `window` anyway?): - - ```html run - - ``` - -**Using `