New block-level scopes, lets, and const are available in ES6

1. The var command

Function scope

When a variable is declared using var, it is automatically added to the most recent context. If a variable is initialized undeclared, it is automatically added to the global context

function add(num1,num2){
	var sum=sum1+sum2
	return sum
}

let result=add(10.20)
console.log(sum)	Error :sum is not a valid variable
Copy the code

Here, the function add defines a local variable sum, which is returned as the value of the function, but is not accessible outside the function.

function add(num1,num2){
	sum=sum1+sum2
	return sum
}

let result=add(10.20)
console.log(sum)	Error :sum is not a valid variable
Copy the code

If the keyword var is omitted, sum is added to the global context after the call to add.

Note: Initializing variables without declaring them is a very common error in JS and can cause a lot of problems.


2. Let the command

Basic usage

ES6 added the let command to declare variables. Its use is similar to var, but the declared variable is only valid within the code block in which the let command resides. (i.e., block-level scope)

{
  let a = 10;
  var b = 1;
}

a // ReferenceError: a is not defined.
b / / 1
Copy the code

The above code declares two variables, let and var, respectively, in the code block. These two variables are then called outside of the code block, with the let variable reporting an error and the var variable returning the correct value. This indicates that the variable declared by the LET is valid only in the code block in which it is located.

The following code, if var is used, will output 10.

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6] ();/ / 10
Copy the code

In the above code, the variable I is declared by the var command and is valid globally, so there is only one variable I globally. The value of variable I changes each time through the loop, and the console.log(I) inside the function assigned to array A refers to the global I. That is, all the I’s in array A refer to the same I, causing the runtime to print the value of the last round of I, which is 10.

If let is used, the declared variable is only valid in the block-level scope, and the final output is 6.

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6] ();/ / 6
Copy the code

In the above code, the variable I is declared by let, and the current I is only valid for this loop, so each loop I is actually a new variable, so the final output is 6. You might ask, if the variable I for each cycle is redeclared, how does it know the value of the previous cycle and thus calculate the value of the current cycle? This is because the JavaScript engine internally remembers the value of the previous cycle, and when it initializes the variable I of this cycle, it evaluates on the basis of the previous cycle.

There is no variable promotion

The “variable promotion” phenomenon occurs when the var command is used, that is, the variable can be used before the declaration and its value is undefined. This is somewhat strange, as normal logic dictates that variables should be used only after the statement has been declared.

To correct this, the let command changes the syntactic behavior so that the variables it declares must be used after the declaration or an error will be reported.

// var case
console.log(foo); / / output is undefined
var foo = 2;

// let
console.log(bar); / / error ReferenceError
let bar = 2;
Copy the code

In the above code, the variable foo is declared with the var command, and the variable promotion occurs. That is, when the script starts running, the variable foo already exists, but has no value, so undefined is printed. The variable bar is declared with the let command, and no variable promotion occurs. This means that the variable bar does not exist until it is declared, and an error will be thrown if it is used.

Temporary dead zone

As long as the let command exists in the block-level scope, the variables it declares are “binding” to the region, no longer subject to external influence.

var tmp = 123;

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

In the above code, there is a global variable TMP, but in the block-level scope, let also declared a local variable TMP, causing the latter to bind the block-level scope. Therefore, before let declared the variable, TMP assignment will report an error.

ES6 explicitly states that if there are let and const commands in a block, the variables declared by the block to those commands form a closed scope from the start. Any time these variables are used before declaration, an error is reported.

In short, the variable is not available within the code block until it is declared using the let command. This is grammatically known as a “temporal dead zone” (TDZ).

Duplicate declarations are not allowed

Let does not allow the same variable to be declared twice in the same scope.

/ / an error
function func() {
  let a = 10;
  var a = 1;
}

/ / an error
function func() {
  let a = 10;
  let a = 1;
}
Copy the code

Why do you need block-level scopes?

In the first scenario, the inner variables may override the outer variables.

var tmp = new Date(a);function f() {
  console.log(tmp);
  if (false) {
    var tmp = 'hello world';
  }
}

f(); // undefined
Copy the code

The if block uses the TMP variable in the outer layer and the TMP variable in the inner layer. The TMP variable in the inner layer overwrites the TMP variable in the outer layer.

In the second scenario, loop variables used to count are exposed as global variables.

var s = 'hello';

for (var i = 0; i < s.length; i++) {
  console.log(s[i]);
}

console.log(i); / / 5
Copy the code

In the code above, the variable I is used only to control the loop, but when the loop ends, it does not disappear and leaks out as a global variable.

ES6 block-level scope

function f1() {
  let n = 5;
  if (true) {
    let n = 10;
  }
  console.log(n); / / 5
}
Copy the code

The above function has two code blocks that declare the variable n and print 5. This means that the outer code block is not affected by the inner code block. If you use var to define n both times, the output is 10.

3. The const command

Const declares a read-only constant. Once declared, the value of a constant cannot be changed.

const PI = 3.1415;
PI / / 3.1415

PI = 3;
// TypeError: Assignment to constant variable.
Copy the code

A variable declared by const may not change its value, which means that a const, once declared, must be initialized immediately and cannot be left for later assignment.

Const has the same scope as the let command: it is only valid in the block-level scope in which the declaration is made.

Constants declared by the const command are also non-promoted and have temporary dead zones that can only be used after the declared position.

A constant declared by const, like let, cannot be declared repeatedly.

nature

What const actually guarantees is not that the value of the variable cannot be changed, but that the data stored at the memory address to which the variable points cannot be changed. For data of simple types (values, strings, booleans), the value is stored at the memory address to which the variable points, and is therefore equivalent to a constant. But for complex type data (mainly objects and arrays), variable pointing to the memory address, save only a pointer to the actual data, const can guarantee the pointer is fixed (i.e., always points to the other a fixed address), as far as it is pointing to the data structure of variable, is completely unable to control. Therefore, declaring an object as a constant must be done with great care.

const foo = {};

// Add an attribute to foo
foo.prop = 123;
foo.prop / / 123

// If foo points to another object, an error is reported
foo = {}; // TypeError: "foo" is read-only
Copy the code

In the code above, the constant foo stores an address that points to an object. Only the address is immutable, that is, you can’t point foo to another address, but the object itself is mutable, so you can still add new attributes to it.

Excerpts from Ruan Yifeng’s blog