Let and const are new ES6 keywords for declaring variables and constants. What do they do? What are their properties? How are they different from the variables defined by VAR?

Let and const

A variable is a variable that can be changed after definition, and a constant that cannot be changed after definition.

1. Variables and constants

In ES6, let is used to define variables, and const is used to define constants. That is, let variables can be modified, and const constants cannot be modified. This feature is currently natively supported by most browsers, but for the few that don’t, we can use Babel to compile it into ES5 syntax. Here’s how the code compiled with Babel differs:

// ES6
let a = 1;
const b = 2;
Copy the code
// Babel is compiled
"use strict";

var a = 1;
var b = 2;
Copy the code

Feels the same, huh?? Don’t worry, add another code:

// ES6
let a = 1;
const b = 2;
b = 3;
Copy the code
// Babel is compiled
"use strict";

function _readOnlyError(name) { throw new Error("\" " + name + "\" is read-only"); }

var a = 1;
var b = 2;
b = (_readOnlyError("b"), 3);
Copy the code

This should make it easy to see the difference. When we mutate a constant, we throw an error telling you that the value is read-only.

B = (_readOnlyError(“b”), 3) = _readOnlyError(“b”) &&3

Note: Since values defined by const are immutable, be careful when defining reference types with const. If the value is a const of a reference type, it is possible to change the attribute, but it is generally not recommended.

const obj = {};
obj.a = 1;
obj.b = 2;
obj; // => {a: 1, b: 2}

obj = {}; / / = > an error
Copy the code

2. The definition is initialized

Since const is defined as a constant, it must be initialized at the time it is defined or an error will be reported. Let, however, has no such limitation. It defines variables that can be initialized later:

let a;
a = 1;

const b; // Uncaught SyntaxError: Missing initializer in const declaration
b = 2;
Copy the code

The above code fails Babel compilation because it directly violates the syntactic nature of const

Let and var

Let and var are two ways to declare variables. They have the following differences:

1. Different scopes

  • letA declared variable creates its own block-level scope within the block-level code that defines it and its included subblocks, and does not automatically apply to global variableswindowTo bind properties.
  • varA defined variable is scoped to the function that defines it, or to the global object, and is automatically applied to the global objectwindowOf the bound property.

The difference between being able to create your own block-level scope comes up with a well-trotted interview question:

var result = [];
(function () {
  for (var i = 0; i < 5; i++) {
    result.push(function () {
      console.log(i);
    });
  }
})();
result.forEach(function (item) {
  item()
});
// => Print out five 5's
Copy the code

Why are five 5’s printed instead of 0,1,2,3,4 as expected? Because var will not create your own scope, and js itself is not block-level scope of the concept, the for loop variables defined and directly in the anonymous function variables, so when the five functions are drawn, cycle has already been completed, and the function to read the above storage layer scope variable I, It’s already been added up to 5.

However, this problem can be solved by replacing the var keyword with let:

var result = [];
(function () {
  for (let i = 0; i < 5; i++) {
    result.push(function () {
      console.log(i);
    });
  }
})();
result.forEach(function (item) {
  item()
}); / / = > 0,1,2,3,4
Copy the code

Let’s see what Babel translates into:

"use strict";

var result = [];

(function () {
  var _loop = function _loop(i) {
    result.push(function () {
      console.log(i);
    });
  };

  for (var i = 0; i < 5; i++) {
    _loop(i);
  }
})();

result.forEach(function (item) {
  item();
});
Copy the code

As can be seen from the above code, let creates a scope by creating a function, defining a variable with the same name inside the function and passing it externally.

2. Variable declaration enhancement

  • letA defined variable does not undergo variable declaration promotion, meaning that it must be defined before it can be accessed.
  • varThe variable defined has variable declaration promotion, so the variable can be accessed before the variable is defined, and the value isundefined.
console.log(a); // undefined
var a = 1;

console.log(b); // Uncaught ReferenceError: Cannot access 'b' before initialization
let b = 2;
Copy the code

Let’s also look at what the code looks like when compiled:

"use strict";

console.log(a);
var a = 1;

console.log(b);
var b = 2;
Copy the code

It seems that Babel is unable to compile the syntax that prevents variable declarations from being promoted. The features that let declarations cannot be promoted should be supported and implemented by the browser’s internal JS execution engine.

3. Temporary dead zones

As long as the let/const command exists in the block-level scope, the variables/constants declared by it are “binding” to the area and are no longer affected by external influences. ES6 explicitly states that if there are let and const commands in a block, the variables declared by the block to those commands are closed from the start, and any use of those variables before declaration will result in an error. This feature is also known as a temporary dead zone.

var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError: tmp is not defined
  let tmp;
}
Copy the code

This feature is also supported and implemented by the browser’s internal JS execution engine. Babel does not support compilation of this feature, but simply compiles let to var. But interestingly, since let can build its own independent scope in the if block, Babel changes the name TMP to simulate the implementation of block-level scope creation:

"use strict";

var tmp = 123;

if (true) {
  _tmp = 'abc';

  var _tmp;
}
Copy the code

4. Can I repeat the definition

  • letDefined variables, once defined, are not allowed to be redefined.
  • varA defined variable can be redefined.
var a = 1;
var a = 2;

let b = 3;
let b = 4; // Uncaught SyntaxError: Identifier 'b' has already been declared
Copy the code

This code also fails at Babel compilation because it directly violates the syntax feature that let variables cannot be redefined.

conclusion

It’s not that complicated, but we can summarize it briefly:

letFeatures:

  • Create block-level scopes.

  • A definition cannot be redefined.

  • There is no variable promotion.

  • There are temporary dead zones.

  • No longer mount to top-level objects (window objects/global objects) when defined in global scope

    // Browser environment
    var a = 1;
    window.a; / / = > 1
    
    let b = 2;
    window.b; // => undefined
    Copy the code

constFeatures:

  • withlet
  • Once an assignment is initialized, it cannot be modified later
  • It must be initialized when it is defined

This article has been included in the front-end interview Guide column

Relevant reference

  • Let and const commands

Previous content recommended

  1. Thoroughly understand throttling and anti-shaking
  2. [Basic] Principles and applications of HTTP and TCP/IP protocols
  3. 【 practical 】 WebPack4 + EJS + Express takes you through a multi-page application project architecture
  4. Event Loop in browser
  5. Interviewer: Tell me about the execution context
  6. Interviewer: Talk about scopes and closures
  7. Interviewer: Talk about prototype chains and inheritance
  8. Interviewer: Talk about modularity in JS