5

I was doing a test in JavaScript and I noticed that using the let keyword like

let variable = "I am a variable";
console.log(window.variable);

did not add a variable property to the window object. Does this mean that it does not exist in the global scope?

Could I declare variables without having to scope them inside a function or an IIFE?

I did search for this but could not find anything. Everyone says to use functions like {}() or simply access a unique global variable that contains the code, but seeing this made me wonder if it could be used for the purpose of avoiding these things.

1
  • 1
    If the question is: "are top level lets a replacement for IIFEs and the encapsulation provided by a function's lexical scope?" then I think the answer would be a resounding no. The ES2015 replacement for global namespace objects and many current uses of IIFEs is modules. Commented Mar 31, 2016 at 22:17

1 Answer 1

18

The let statement cannot be used to avoid global variables in the way that you suggest. A top-level let statement will still create variables in the global scope, it just won't create them as properties of the "global object" (typically window).

<script>
  'use strict';
  let fromLet = 'from let';
  var fromVar = 'from var';
</script>

<script>
  console.log(fromLet);        // 'from let'
  console.log(fromVar);        // 'from var'
  console.log(window.fromLet); // undefined
  console.log(window.fromVar); // 'from var'
</script>

This behaviour is primarily described in Section 8.1.1.4: Global Environment Records of the ECMAScript 6 specification. The gist of it is that there is a single global scope/namespace, but its values can be recorded in two different places. Global built-ins, function declarations, var declarations, and function* (generator) declarations are recorded as properties of the global object, while everything else global (from let, const, class, and other new constructs) is stored in an internal "environment record" which is not exposed as an object in the runtime.

Here are a few relevant excerpts to start from if you'd like to dig in to the details.

A global Environment Record is used to represent the outer most scope that is shared by all of the ECMAScript Script elements that are processed in a common Realm (8.2). A global Environment Record provides the bindings for built-in globals (clause 18), properties of the global object, and for all top-level declarations (13.2.8, 13.2.10) that occur within a Script.

Properties may be created directly on a global object. Hence, the object Environment Record component of a global Environment Record may contain both bindings created explicitly by FunctionDeclaration, GeneratorDeclaration, or VariableDeclaration declarations and binding created implicitly as properties of the global object. In order to identify which bindings were explicitly created using declarations, a global Environment Record maintains a list of the names bound using its CreateGlobalVarBindings and CreateGlobalFunctionBindings concrete methods.

Table 18 — Additional Fields of Global Environment Records

[[ObjectRecord]]: Object Environment Record

Binding object is the global object. It contains global built-in bindings as well as FunctionDeclaration, GeneratorDeclaration, and VariableDeclaration bindings in global code for the associated Realm.

[[DeclarativeRecord]]: Declarative Environment Record

Contains bindings for all declarations in global code for the associated Realm code except for FunctionDeclaration, GeneratorDeclaration, and VariableDeclaration bindings.

[[VarNames]]: List of String

The string names bound by FunctionDeclaration, GeneratorDeclaration, and VariableDeclaration declarations in global code for the associated Realm.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.