3

As shown in the code below, I used var value = 1, and the value obtained is 1 . I can understand this because return this.value here the this points to the window, so I can print out the global variable value.

var value = 1;
let obj = {
  getValue: function() {
    return function() {
      return this.value;
    }
  }
}
console.log(obj.getValue()());  // 1

But if I use let to declare the value, I can't get the value of the value, the print is undefined. This is very puzzled, whether it is using let, or var statement, value is a global variable. Why is there such a difference?

let value = 1;
let obj = {
  getValue: function() {
    return function() {
      return this.value;
    }
  }
}
console.log(obj.getValue()());  // undefined

Do you know why? Can you tell me? Thank you very much.

Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
DangoSky
  • 185
  • 1
  • 2
  • 15
  • I was very confused by this as well. It is important to note that it's supposed to be an alternative to using var, so you either use let and const or var. They were created to be alternatives to var. You use const if you don't want var to ever be changed. You use let if you want var to change according to where it is in the document, as stated above the block, statement or expression. – Yoko Ishioka May 26 '19 at 06:58

4 Answers4

2

At the top level of programs and functions, let, unlike var, does not create a property on the global object. For example: Scopping rules MDN

var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined
Code Maniac
  • 37,143
  • 5
  • 39
  • 60
2

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

Using var value = 1; this would still output 1. But with let it outputs undefined because the function is defined lexically outside the block in which value was declared, so it can't access it, even by going through the global object.

Or as MDN puts it:

let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used.

That's let's purpose for which it was designed.

melpomene
  • 84,125
  • 8
  • 85
  • 148
1

Because let doesn't add anything to the global window object - that's why dynamic variable names like this:

var dynamicR = "Hello World!";
console.log(this["dynamic" + "R"]);

Don't work with let or const:

let dynamicR = "Hello World!";
console.log(this["dynamic" + "R"]);

So when you're calling the function, it's looking in the window object due to the calling context, and as demonstrated above, this won't work with let.

Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
  • So where is let dynamicR being defined then if not in the window? – abelito May 26 '19 at 06:51
  • 1
    @abelito [Explained here](https://stackoverflow.com/a/41848066/10221765), it's stored in the environment (read global) *record* rather than environment *object*. – Jack Bashford May 26 '19 at 06:52
0

From MDN's documentation:

let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike the var keyword, which defines a variable globally, or locally to an entire function regardless of block scope.

and:

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

ray
  • 26,557
  • 5
  • 28
  • 27