38

Let's take the following code for example:

const constVar = 'some string';
let letVar = 'some string';
var varVar = 'some string';

(function() {
  console.log(window.constVar); // prints undefined
  console.log(window.letVar); // prints undefined
  console.log(window.varVar); // prints 'some string'
})();

According to the description of the const statement by mdn:

This declaration creates a constant whose scope can be either global or local to the block in which it is declared.

And I assume let works in the same way.

In this case, the "block" is contained within the global scope. I guess the important distinction here is that while const constVar is "globally" accessible it still doesn't define it on the window object.

Which leads me to think that global scope and the window object are disparate. Which ultimately leads to 2 questions.

  1. Why do variables declared using the var keyword get defined on window and variables declared with const and let not defined on window?

  2. What is the difference between "global scope" and the window object provided to us by browsers.

Andrew Kim
  • 3,145
  • 4
  • 22
  • 42
  • 1
    window also inherits from other places, like Object.prototype and elements with IDs for example. "Accidental" (intrinsic) globals were never a great idea anyway, so the newer specs clean up "slop" from prior JS implementations without breaking existing code. This is slightly outside of JS proper, being an implementation detail; eg. Node.js has no `window`. – dandavis Mar 06 '19 at 19:12
  • @VLAZ yeah i guess that is the question i'm getting at, but like you said, it seems like the intended behavior was never to even let `var` define things on `window` – Andrew Kim Mar 06 '19 at 19:42
  • @AndrewKim I'm not sure you can say that about the intention behind `var` when ECMAScript version 1 explicitly defines that `var` declarations become properties of the global object [page 51 in this document or page 62 in your PDF viewer](https://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%201st%20edition,%20June%201997.pdf). – VLAZ Mar 06 '19 at 19:51

2 Answers2

34

1. Why do variables declared using the var keyword get defined on window and variables declared with const and let not defined on window?

Because the specification says so. If you are asking for the reason behind that decision, then you should reach out to the specification maintainers.

Classes do not become properties of the global object either btw.

2. What is the difference between "global scope" and the window object provided to us by browsers.

There are two types of base environment records according to the spec:

  • Declarative Environment Record
  • Object Environment Record

A Declarative Environment Record is basically your standard environment that you get when calling a function. All bindings (variables, constants, etc) are defined in some internal data structure that cannot be accessed from normal code.

An Object Environment Record on the other hand uses an actual JavaScript object to store bindings. This is used for example by the now deprecated with statement:

with({foo: 42}) {
  console.log(foo);
}

Now, a Global Environment Record actually consists of two environment records: A declarative environment record and an object environment record. The object environment is backed by the global object, i.e. window and contains var declarations and other globals that the browser provides. The declarative environment contains the let, const, class, etc declarations.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • this makes sense(the specs rationale) If you had to venture your best guess, what would you say is that rationale they took for that differentiation between variable assignment statements with regard to how they interact or don't interact with the `window` object? – Andrew Kim Mar 06 '19 at 19:46
  • I'm not sure tbh. Having everything on a global object is not worse than putting everything into global scope. However, the global object is defined as a "host object", which means it can actually behave however the implementation wants. Maybe this made it harder to enforce `const` bindings (i.e. `const foo = 42; window.foo = 21;`). – Felix Kling Mar 06 '19 at 19:56
  • @JonasWilms: There is always only one global scope in an environment. All `` on a page share the same environment. Whether or not a global variable is also a property of `window` doesn't make a difference. – Felix Kling Mar 06 '19 at 20:13
  • @felix whoops, I actually thought a new one would be created for each script ... then your point about constants seems to go into a good direction ... – Jonas Wilms Mar 06 '19 at 20:16
  • @JonasWilms: There is module scope for scripts loaded as modules. – Felix Kling Mar 06 '19 at 20:17
7

From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

This declaration creates a constant whose scope can be either global or local to the block in which it is declared. Global constants do not become properties of the window object, unlike var variables. An initializer for a constant is required; that is, you must specify its value in the same statement in which it's declared (which makes sense, given that it can't be changed later).

To answer your 2nd question, global variable can be accessed through window object. However, there is an exception for const.

Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367