A glimpse into the tube ECMAScript 61_ Let&const

let

Basic Usage
ES6 adds the let command to declare variables. Its usage is similar to var, but the declared variables are only valid in the code block where the let command is located.

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

a // ReferenceError: a is not defined.
b // 1

for loop counters, it is appropriate to use the let command.

for (let i = 0; i < 10; i++) {
  // ...
}

console.log(i);
// ReferenceError: i is not defined

In the above code, the counter i is only valid in the for loop. If it is referenced outside the loop, an error will be reported

No variable promotion
The var command will cause "variable promotion", that is, the variable can be used before declaration, and the value is undefined. This phenomenon is somewhat strange. According to the general logic, variables should be used after the declaration statement.
To correct this phenomenon, the let command changes the syntax behavior. The variables it declares must be used after the declaration, or an error will be reported.

// var situation
console.log(foo); // Output undefined
var foo = 2;
// let
console.log(bar); // Error ReferenceError
let bar = 2;

Temporary deadband
As long as there is a let command in the block level scope, the variables declared by it will "bind" this area and will no longer be affected by the outside.

var tmp = 123;

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

In the above code, there is a global variable tmp, but the let in the block level scope declares a local variable tmp, which causes the latter to bind the block level scope. Therefore, an error will be reported when assigning a value to tmp before the let declares a variable.

ES6 clearly stipulates that if there are let and const commands in the block, the variables declared by the block for these commands form a closed scope from the beginning. If these variables are used before declaration, an error will be reported. In summary, within a code block, a variable is not available until it is declared with the let command. This is called "temporary dead zone" (TDZ) in syntax.

if (true) {
  // TDZ start
  tmp = 'abc'; // ReferenceError
  console.log(tmp); // ReferenceError

  let tmp; // TDZ end
  console.log(tmp); // undefined

  tmp = 123;
  console.log(tmp); // 123
}

"Transient deadband" also means that typeof is no longer a 100% safe operation.

typeof x; // ReferenceError
let x;

For comparison, if a variable is not declared at all, using typeof will not report an error.

typeof undeclared_variable // "undefined"

Some "dead zones" are hidden and not easy to find.

function bar(x = y, y = 2) {
  return [x, y];
}

bar(); // Error reporting

In the above code, the reason why calling the bar function reports an error (some implementations may not report an error) is that the default value of parameter x is equal to another parameter y. at this time, y has not been declared and belongs to the "dead zone". If the default value of Y is x, no error will be reported because X has already been declared.

function bar(x = 2, y = x) {
  return [x, y];
}
bar(); // [2, 2]
In addition, the following code will also report an error, and var The behavior of is different.

// No error
var x = x;

// Error reporting
let x = x;
// ReferenceError: x is not defined

The error in the above code is also due to the temporary dead zone. When using let to declare a variable, an error will be reported as long as the variable is used before the declaration is completed. This is the case in the above line. Before the declaration statement of variable x is completed, the value of X is retrieved, resulting in the error "x undefined".

In short, the essence of a temporary dead zone is that as soon as the current scope is entered, the variable to be used already exists, but cannot be obtained. The variable can be obtained and used only when the line of code declaring the variable appears.

Duplicate declaration not allowed
let does not allow the same variable to be declared repeatedly within the same scope.

Block level scope
let actually adds a block level scope to JavaScript.

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

The above function has two code blocks, both of which declare the variable n and output 5 after running. This means that the outer code block is not affected by the inner code block. If you use var to define variable n twice, the final output value is 10.

You should avoid declaring functions within a block level scope. If necessary, it should also be written as a function expression instead of a function declaration statement.

// The function declaration statement within the block level scope is not recommended
{
  let a = 'secret';
  function f() {
    return a;
  }
}

// Within a block level scope, function expressions are preferred
{
  let a = 'secret';
  let f = function () {
    return a;
  };
}

const

Basic Usage
const declares a read-only constant. Once declared, the value of the constant cannot be changed.
The variable declared by const must not change its value, which means that once const declares a variable, it must be initialized immediately and cannot be left for later assignment. For const, an error will be reported if it only declares that it does not assign a value.
The scope of const is the same as that of the let command: it is only valid within the block level scope where the declaration is located.
Constants declared by the const command are not promoted, and there is also a temporary dead zone, which can only be used after the declared position.

if (true) {
  console.log(MAX); // ReferenceError
  const MAX = 5;
}

Constants declared by const, like let s, cannot be declared repeatedly.

const actually guarantees that the data stored at the memory address pointed to by the variable cannot be changed, not the value of the variable.

globalThis object
The JavaScript language has a top-level object that provides a global environment (that is, a global scope) in which all code runs. However, top-level objects are not unified in various implementations.

  1. In the browser, the top-level object is window, but Node and Web Worker do not have windows.
  2. In browsers and web workers, self also points to the top-level object, but Node does not have self.
  3. In Node, the top-level object is global, but other environments do not support it.

In order to get the top-level object in various environments, the same code now generally uses the this variable, but it has limitations.

  1. In the global environment, this returns the top-level object. However, in the Node module and ES6 module, this returns the current module.
  2. This in the function, if the function is not run as a method of the object, but simply as a function, this will point to the top-level object. However, in strict mode, this will return undefined.
  3. Whether in strict mode or normal mode, new Function('return this') () always returns a global object. However, if the browser uses CSP (Content Security Policy), the eval and new Function methods may not be available

To sum up, it is difficult to find a way to get the top-level object in all cases. Here are two barely usable methods.

// Method 1
(typeof window !== 'undefined'
   ? window
   : (typeof process === 'object' &&
      typeof require === 'function' &&
      typeof global === 'object')
     ? global
     : this);

// Method II
var getGlobal = function () {
  if (typeof self !== 'undefined') { return self; }
  if (typeof window !== 'undefined') { return window; }
  if (typeof global !== 'undefined') { return global; }
  throw new Error('unable to locate global object');
};

ES2020 introduces globalThis as the top-level object at the level of language standards. In other words, globalThis exists in any environment. You can get the top-level object from it and point to this in the global environment.

The gasket library global this simulates this proposal, which can be obtained in all environments.

Posted by ihsreal on Mon, 30 May 2022 07:00:44 +0530