What is globalThis, and why should you start using it?
Tags: javascript, webdev
Published: 2019-12-03 16:30:11

---
title: What is globalThis, and why should you start using it?
published: true
date: 2019-12-02 19:30:12 UTC
tags: javascript,webdev
canonical_url: https://blog.logrocket.com/what-is-globalthis-why-use-it/
cover_image: https://thepracticaldev.s3.amazonaws.com/i/ayi6f8iovrxr7kq6kxcd.jpeg
---
**Written by [Faraz Kelhini](https://blog.logrocket.com/author/farazkelhini/)**✏️

The JavaScript language is increasingly used in a wide variety of environments. In addition to the web browser, which is the most common type of host environment for JavaScript, you can run JavaScript programs in servers, smartphones, and even robotic hardware.

Each environment has its own object model and provides a different syntax to access the global object. In the web browser, for example, the global object is accessible via `window`, `self`, or `frames`. In Node.js, however, these properties don’t exist, and you must use `global` instead. In Web Workers, only `self` is available.

These different ways of referencing the global object have made it tough to write a portable JavaScript code that works in multiple environments. Fortunately, there’s a [proposal in the works](https://github.com/tc39/proposal-global) that aims to fix this issue by introducing a standard property called `globalThis` that will be available in all environments.

In this article, we’ll first look at the global object in popular JavaScript environments and then see how `globalThis` provides a unified mechanism to access it.

[![LogRocket Free Trial Banner](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/f760c-1gpjapknnuyhu8esa3z0jga.png?resize=1200%2C280&ssl=1)](https://logrocket.com/signup/)

## `window`

The `window` property is used to refer to the global object of the current document in the browser environment. At the top level of the code, variables declared using the `var` keyword become properties of `window` and are accessible from anywhere in the code:

```jsx
var a = [10, 20];

console.log(window.a);          // → [10, 20]
console.log(a === window.a);    // → true
```

Normally, it’s not necessary to directly refer to `window` when using its properties because the reference is implied. However, when there is a local variable with the same name as the global variable, using `window` is the only option:

```jsx
var a = 10;

(function() {
  var a = 20;   
  console.log(a);           // → 20
  console.log(window.a);    // → 10
})();
```

As you can see, `window` is very useful for referencing the global object, regardless of the scope in which the code is running. Note that `window` actually references `window.window`. So, `window.window === window`.

Besides the standard JavaScript properties and methods, the `window` object contains several additional properties and methods that allow us to control the web browser window as well as the document itself.

## `self`

The Web Workers API doesn’t have a `Window` object because it has no browsing context. Instead, it provides the `WorkerGlobalScope` interface containing the data that’s normally carried by `window`.

To access the global object in Web Workers, we use `self`, which is a synonym for the `window` property of the `Window` object. Similar to `window`, `self` is a reference to the global object and can be used to make references explicit rather than implicit:

```jsx
// a web worker
console.log(self);    // => DedicatedWorkerGlobalScope {...}

var a = 10;

console.log(self.a);          // → 10
console.log(a === self.a);    // → true
```

In a browser environment, this code would log `Window` rather than `DedicatedWorkerGlobalScope`. Because `self`‘s value changes depending on the environment in which it is used, it’s sometimes preferable to `window`. While `self` references `WorkerGlobalScope.self` in the web worker context, it references `window.self` in the browser context.

It’s important not to confuse the `self` property with the common JavaScript pattern of declaring a local variable, which is used to maintain a reference to a context. For instance:

```jsx
const obj = {
  myProperty: 10,
  myMethod: function(){
    console.log(this === obj);    // => true

    // store the value of this in a variable for use in nested functions
    const self = this;

    const helperFunction = (function() {
      console.log(self === obj);  // => true (self refers to the outer this value)
      console.log(this === obj);  // => false (this refers to the global object. In strict mode, it has a value of undefined)
    })();
  }
};

// invoke myMethod on the object obj.
obj.myMethod();
```

## `frames`

Another way to access the global object in the browser environment is to use the `frames` property, which works similar to `self` and `window`:

```jsx
// browser environment
console.log(frames);    // => Window {...}
```

This read-only property is usually used to obtain a list of sub-frames of the current window. For example, you can use `window.frames[0]` or `frames[0]` to access the first frame.

## `global`

In Node.js, you can access the global object using the `global` keyword:

```jsx
// node environment
console.log(global);    // => Object [global] {...}
```

`window`, `self`, or `frames` won’t work in the Node environment. Keep in mind that the top-level scope in Node.js is not the global scope. In browsers, `var abc = 123` will create a global variable. In Node.js, however, the variable will be local to the module itself.

## `this`

In browsers, you can use the `this` keyword at the top level of your program to reference the global object:

```jsx
this.foo = 123;
console.log(this.foo === window.foo);    // => true
```

`this` inside functions running in non-strict mode or arrow functions also references the global object. But that’s not the case with functions running in strict mode, in which `this` has a value of `undefined`:

```jsx
(function() {
  console.log(this);    // => Window {...}
})();

(() => {
  console.log(this);    // => Window {...}
})();

(function() {
  "use strict";
  console.log(this);    // => undefined
})();
```

In Node modules, `this` at the top level doesn’t reference the global object. Instead, it has the same value as `module.exports`. Inside functions (Node environment), the value of `this` is determined based on how the function is called. In JavaScript modules, `this` at the top level is `undefined`.

## Introducing `globalThis`

`globalThis` aims to consolidate the increasingly fragmented ways of accessing the global object by defining a standard global property. The `globalThis` proposal is currently at stage 4, which means it’s ready for inclusion in the ES2020 standard. All popular browsers, including Chrome 71+, Firefox 65+, and Safari 12.1+, already support the feature. You can also use it in Node.js 12+.

```jsx
// browser environment
console.log(globalThis);    // => Window {...}

// node.js environment
console.log(globalThis);    // => Object [global] {...}

// web worker environment
console.log(globalThis);    // => DedicatedWorkerGlobalScope {...}
```

By using `globalThis`, your code will work in window and non-window contexts without having to write additional checks or tests. In most environments, `globalThis` directly refers to the global object of that environment. In browsers, however, a proxy is used internally to take into account iframe and cross-window security. In practice, it doesn’t change the way you write your code, though.

Generally, when you’re not sure in what environment your code will be used, or when you want to make your code executable in different environments, the `globalThis` property comes in very handy. You’ll have to use a polyfill to implement the feature on older browsers that do not support it, however.

On the other hand, if you’re certain what environment your code is going to be used in, then use one of the existing ways of referencing the environment’s global object and save yourself from the need to include a polyfill for `globalThis`.

## Creating a `globalThis` polyfill

Prior to the introduction of `globalThis`, a common way to access the global object across different environments was to use the following pattern:

```jsx
function getGlobalObject() {
  return Function('return this')();
}

if (typeof getGlobalObject().Promise.allSettled !== 'function') {
  // the Promise.allSettled() method is not available in this environment
}
```

The problem with this code is that the `Function` constructor and `eval` cannot be used in websites that enforce [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP). Chrome’s extension system also doesn’t allow such code to run because of CSP.

Another pattern to reference the global object is as follows:

```jsx
function getGlobalObject() {
  if (typeof globalThis !== 'undefined') { return globalThis; }
  if (typeof self !== 'undefined') { return self; }
  if (typeof window !== 'undefined') { return window; }
  if (typeof global !== 'undefined') { return global; }
  throw new Error('cannot find the global object');
};

if (typeof getGlobalObject().Promise.allSettled !== 'function') {
  // the Promise.allSettled() method is not available in this environment
}
```

This pattern is commonly used on the web. But this too has [several flaws](https://mathiasbynens.be/notes/globalthis#naive-polyfill), making it unreliable in certain situations. Fortunately, Mathias Bynens at Chrome DevTools [has come up with a creative pattern](https://mathiasbynens.be/notes/globalthis#robust-polyfill) that doesn’t suffer from those shortcomings:

```jsx
(function() {
  if (typeof globalThis === 'object') return;
  Object.defineProperty(Object.prototype, '__magic__', {
    get: function() {
      return this;
    },
    configurable: true // This makes it possible to `delete` the getter later.
  });
  __magic__.globalThis = __magic__; // lolwat
  delete Object.prototype.__magic__;
}());

// Your code can use `globalThis` now.
console.log(globalThis);
```

This polyfill is a more robust solution compared to other approaches, but it’s still not perfect. Modifying `Object`, `Object.defineProperty`, or `Object.prototype. __defineGetter__ ` could break the polyfill, as Mathias mentions.

## Wrapping up

It’s difficult to write a portable JavaScript code that works in multiple environments. Each host environment has a slightly different object model. As a result, to access the global object, you need to use different syntax in different JavaScript environments.

With the introduction of the `globalThis` property, accessing the global object will become much simpler, and it will no longer be necessary to detect the environment in which the code is running.

At first glance, `globalThis` seems like an easy thing to polyfill; but in practice, it’s very complicated to do correctly. All existing workarounds are imperfect and might introduce bugs if you’re not careful.

ECMAScript is quickly evolving, and you can expect new features to be introduced more often. To get updated on the latest additions to the specs, check out the list of [finished proposals](https://github.com/tc39/proposals/blob/master/finished-proposals.md).

## Implementing New JS Features? Understand How JavaScript Errors Affect Your Users. 

Tracking down the cause of a production JavaScript exception or error is time consuming and frustrating. If you’re interested in monitoring JavaScript errors and seeing how they affect users, [try LogRocket](https://logrocket.com/signup/).[![LogRocket Dashboard Free Trial Banner](https://i2.wp.com/blog.logrocket.com/wp-content/uploads/2019/10/errors-screenshot.png?ssl=1)](https://logrocket.com/signup/)[https://logrocket.com/signup/](https://logrocket.com/signup/)

[LogRocket](https://logrocket.com/signup/) is like a DVR for web apps, recording literally everything that happens on your site.LogRocket enables you to aggregate and report on errors to see how frequent they occur and how much of your user base they affect. You can easily replay specific user sessions where an error took place to see what a user did that led to the bug.

LogRocket instruments your app to record requests/responses with headers + bodies along with contextual information about the user to get a full picture of an issue. It also records the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.

Enhance your JavaScript error monitoring capabilities – [Start monitoring for free](https://logrocket.com/signup/).
* * *
The post [What is globalThis, and why should you start using it?](https://blog.logrocket.com/what-is-globalthis-why-use-it/) appeared first on [LogRocket Blog](https://blog.logrocket.com).