4.5 The global environment

The global scope is the “outermost” scope – it has no outer scope. Its environment is the global environment. Every environment is connected with the global environment via a chain of environments that are linked by outer environment references. The outer environment reference of the global environment is null.

The global environment record uses two environment records to manage its variables:

  • An object environment record has the same interface as a normal environment record, but keeps its bindings in a JavaScript object. In this case, the object is the global object.

  • A normal (declarative) environment record that has its own storage for its bindings.

Which of these two records is used when will be explained soon.

4.5.1 Script scope and module scopes

In JavaScript, we are only in global scope at the top levels of scripts. In contrast, each module has its own scope that is a subscope of the script scope.

If we ignore the relatively complicated rules for how variable bindings are added to the global environment, then global scope and module scopes work as if they were nested code blocks:

  1. { // Global scope (scope of *all* scripts)
  2. // (Global variables)
  3. { // Scope of module 1
  4. ···
  5. }
  6. { // Scope of module 2
  7. ···
  8. }
  9. // (More module scopes)
  10. }

4.5.2 Creating variables: declarative record vs. object record

In order to create a variable that is truly global, we must be in global scope – which is only the case at the top level of scripts:

  • Top-level const, let, and class create bindings in the declarative environment record.
  • Top-level var and function declarations create bindings in the object environment record.
  1. <script>
  2. const one = 1;
  3. var two = 2;
  4. </script>
  5. <script>
  6. // All scripts share the same top-level scope:
  7. console.log(one); // 1
  8. console.log(two); // 2
  9. // Not all declarations create properties of the global object:
  10. console.log(globalThis.one); // undefined
  11. console.log(globalThis.two); // 2
  12. </script>

4.5.3 Getting or setting variables

When we get or set a variable and both environment records have a binding for that variable, then the declarative record wins:

  1. <script>
  2. let myGlobalVariable = 1; // declarative environment record
  3. globalThis.myGlobalVariable = 2; // object environment record
  4. console.log(myGlobalVariable); // 1 (declarative record wins)
  5. console.log(globalThis.myGlobalVariable); // 2
  6. </script>

4.5.4 Global ECMAScript variables and global host variables

In addition to variables created via var and function declarations, the global object contains the following properties:

  • All built-in global variables of ECMAScript
  • All built-in global variables of the host platform (browser, Node.js, etc.)

Using const or let guarantees that global variable declarations aren’t influencing (or influenced by) the built-in global variables of ECMAScript and host platform.

For example, browsers have the global variable .location:

  1. // Changes the location of the current document:
  2. var location = 'https://example.com';
  3. // Shadows window.location, doesn’t change it:
  4. let location = 'https://example.com';

If a variable already exists (such as location in this case), then a var declaration with an initializer behaves like an assignment. That’s why we get into trouble in this example.

Note that this is only an issue in global scope. In modules, we are never in global scope (unless we use eval() or similar).

Fig. 1 summarizes everything we have learned in this section.

4.5 The global environment - 图1

Figure 1: The environment for the global scope manages its bindings via a global environment record which in turn is based on two environment records: an object environment record whose bindings are stored in the global object and a declarative environment record that uses internal storage for its bindings. Therefore, global variables can be created by adding properties to the global object or via various declarations. The global object is initialized with the built-in global variables of ECMAScript and the host platform. Each ECMAScript module has its own environment whose outer environment is the global environment.