Do Let Statements Create Properties on the Global Object

Do let statements create properties on the global object?

Do let statements create properties on the global object?

According to the spec, no:

A global environment record is logically a single record but it is specified as a composite encapsulating an object environment record and a declarative environment record. The object environment record has as its base object the global object of the associated Realm. This global object is the value returned by the global environment record’s GetThisBinding concrete method. The object environment record component of a global environment record contains the bindings for all built-in globals (clause 18) and all bindings introduced by a FunctionDeclaration, GeneratorDeclaration, or VariableStatement contained in global code. The bindings for all other ECMAScript declarations in global code are contained in the declarative environment record component of the global environment record.

Some more explanation:

  • A declarative environment record stores the bindings in an internal data structure. It's impossible to get a hold of that data structure in any way (think about function scope).

  • An object environment record uses an actual JS object as data structure. Every property of the object becomes a binding and vice versa. The global environment has an object environment object whose "binding object" is the global object. Another example is with.

Now, as the cited part states, only FunctionDeclarations, GeneratorDeclarations, and VariableStatements create bindings in the global environment's object environment record. I.e. only this bindings become properties of the global object.

All other declarations (e.g. const and let) are stored in the global environment's declarative environment record, which is not based on the global object.

A question about let when it acts as a global variable in ES6

As MDN explains:

At the top level of programs and functions, let, unlike var, does not create a property on the global object.

This is because let always creates a lexically scoped variable. If it were to create properties of a global object instead, those properties would be visible to code in other scopes. They wouldn't be lexically scoped anymore, defeating the point of using let.

If you're wondering how there can be "other scopes" not lexically contained within the global scope, there can be multiple script files. Or look at this variation of your example:

let getValue = function() {

return this.value;

};

let value = 1;

console.log(getValue());

In JavaScript; does a let variable declared outside of a block get a global scope?

I don't know if I understand you correctly.

There is no "outside of a block", because even if you use it on the blank page, it is in the "main/global block" but only in the same script. its not available from other scripts.

why don't const and let statements get defined on the window object

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);

}

Can the let keyword be used in JavaScript to avoid global-scoped variables?

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>

How can we explain the differences between let and var in global scope of browser?

As your object method, you used an arrow function, whose context (this value) is bound to the function in which you've declared them.

That is, your getX function's this value will be the global object (window).

Then you try to access the x property of that object, which is 10 (as global-scope var creates properties on the global object) in case of var.

However, let never creates a property on the global object, therefore in your second example, you get undefined.

Try it:

const object = {

method: () => this

}

console.log(object.method() === window) //true

var foo = 1

let bar = 2

console.log(foo, window.foo) // 1 1

console.log(bar, window.bar) // 2 undefined

A javascript 'let' global variable is not a property of 'window' unlike a global 'var'

I hear people say that at the global level, let and var are/behave the
same, but this is not what I am seeing.

Eh, yes and no. To answer your question, in the large majority of cases let and var are the same when declared globally, but there are some differences.

To explain: A global environment record is where JS keeps all the logic and memory values for the code in play. However, this global environment record is really a composite encapsulating an object environment record and a declarative environment record.

Some more explanation:

A declarative environment record stores the bindings in an internal data structure. It's impossible to get a hold of that data structure in any way (think about function scope).

An object environment record uses an actual JS object as data structure. Every property of the object becomes a binding and vice versa. The global environment has an object environment record whose "binding object" is the global object. This would be the Realm, which in most cases is the window object.

So, per the ECMA spec, only FunctionDeclarations, GeneratorDeclarations, and VariableStatements create bindings in the global environment's object environment record.

All other declarations (i.e const and let) are stored in the global environment's declarative environment record, which is not based on the global object. They still declare a variable, but are not a VariableStatement.

TL;DR: Both are still global, but vars are stored in the window object, while lets are stored in a declarative environment that you can't see (just like you can't access a variable in a function scope from outside of the function). When declared globally, both statements are pretty much identical in use.



Related Topics



Leave a reply



Submit