15

I used to check if a global var has been defined with:

if (window['myvar']==null) ...

or

if (window.myvar==null) ...

It works with var myvar

Now that I am trying to switch to let, this does not work anymore.

var myvar='a';
console.log(window.myvar); // gives me a
let mylet='b';
console.log(window.mylet); // gives me undefined

Question: With a global let, is there any place I can look if something has been defined like I could with var from the window object?

More generally:
Is var myvar='a' equivalent to window.myvar='a'?
I hear people say that at the global level, let and var are/behave the same, but this is not what I am seeing.

Fai Ng
  • 670
  • 1
  • 6
  • 13
  • 2
    [`typeof`](http://stackoverflow.com/a/519157) – JJJ Sep 09 '16 at 15:14
  • 11
    Clearly documented: *"At the top level of programs and functions, let, unlike var, does not create a property on the global object."* – https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let – deceze Sep 09 '16 at 15:15
  • 1
    You should never need to *test* whether a variable is declared or not, you should know it. And if you really want them to be global, don't use `let` at all - just assign to a property of `window`. – Bergi Sep 20 '16 at 10:15
  • @Bergi yeah, I am going to go with assigning a prop to window. The reason for testing if something is declared or not is: I have a library of utilities, and some have common dependency. If a dependency is not yet loaded, I would then load it. – Fai Ng Sep 20 '16 at 17:27
  • You should use a loader that remembers itself what it loaded and what not, so there's no need to dynamically test and synchronously (?) load anything. – Bergi Sep 20 '16 at 17:28
  • Hmm, my loader is actually doing what you are describing, and I don't check is some var is declared anymore. I guess I just feel uneasy not having the ability to check if something is declared. – Fai Ng Sep 20 '16 at 17:50

1 Answers1

27

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.

joh04667
  • 6,035
  • 18
  • 30