By Dmitri Pavlutin

Translator: Front-end wisdom

Source: dmitripavlutin


Like it and see. Make it a habit

In this paper,GitHub Github.com/qq449245884…Has included more categories of previous articles, as well as a lot of my documentation and tutorial material. Welcome Star and Perfect, you can refer to the examination points for review in the interview, I hope we can have something together.


First, a simple question. Which of the following code produces an error:

First create instance, then define the class to use:

new Car('red'); // Is there an error? class Car { constructor(color) { this.color = color; }}Copy the code

Or call a function before its definition:

greet('World'); // Is there an error? function greet(who) { return `Hello, ${who}! `; }Copy the code

ReferenceError: Cannot access ‘Car’ before initialization error. The second code works fine.

If your answer is different from the above, or if you make a guess without knowing what’s behind it, then you need to have a knowledge of temporary dead zones (TDZ) **.

TDZ manages the availability of let, const, and class syntax. The way variables work in JS is very important.

1. What is a temporary dead zone

Let’s start with a simple const variable declaration. First declare and initialize the variable, then access it, and everything works fine:

const white = '#FFFFFF';

white; // => '#FFFFFF'
Copy the code

So what happens if you access the white variable before you declare it?

white; // throws `ReferenceError`

const white = '#FFFFFF';

white;
Copy the code

In the line of code preceding the const White = ‘#FFFFFF’ statement, the variable white is in a temporary dead zone.

After accessing White in TDZ, JS throws ReferenceError: Cannot access ‘white’ before initialization

Temporary dead zone semantics prohibit access to a variable before it is declared. It reinforces the order: don’t use anything before you declare it.

2. Statements affected by the TDZ

Take a look at the statements affected by TDZ.

2.1 a const variable

As mentioned earlier, const variables are in the TDZ before the declaration and initialization lines:

// Can't work PI; // throws' ReferenceError 'const PI = 3.14;Copy the code

We must use const after the declaration:

Const PI = 3.14; // Works! pi; / / = > 3.14Copy the code

2.2 let variable

Before declaring rows, let declarations are also affected by TDZ:

// Can't work count; // throws `ReferenceError` let count; count = 10;Copy the code

Again, use the let variable only after the declaration:

let count; // Works! count; // => undefined count = 10; // Works! count; / / = > 10Copy the code

2.3 Class declaration

As you can see in the introduction, class cannot be used until it is defined:

Const myNissan = new Car('red'); // throws `ReferenceError` class Car { constructor(color) { this.color = color; }}Copy the code

2.4 Super () inside constructor

This binding is in TDZ if the parent class is extended before super() is called in the constructor.

class MuscleCar extends Car {
  constructor(color, power) {
    this.power = power;
    super(color);
  }
}

// Does not work!
const myCar = new MuscleCar('blue', '300HP'); // `ReferenceError`
Copy the code

In construction constructor(), this cannot be used before calling super().

TDZ recommends calling the parent constructor to initialize the instance. Once you have done this, the instance is ready to be adjusted in the child constructor.

class MuscleCar extends Car {
  constructor(color, power) {
    super(color);
    this.power = power;
  }
}

// Works!
const myCar = new MuscleCar('blue', '300HP');
myCar.power; // => '300HP'
Copy the code

2.5 Default Function Parameters

Default parameters exist in an intermediate scope, separate from the global and function scopes. The default parameters also follow the TDZ restrictions.

const a = 2;
function square(a = a) {
  return a * a;
}
// Does not work!
square(); // throws `ReferenceError`
Copy the code

Using the argument a on the right side of the expression before declaring the expression a = a generates a reference error about a.

Be sure to use default parameters after declaration and initialization. We can use a special variable init, which is initialized before use:

const init = 2; function square(a = init) { return a * a; } // Works! square(); / / = > 4Copy the code

Var, function, import statements

Contrary to the above statements, var and function definitions are not affected by the TDZ. They are promoted to the top of the current scope.

If you access the var variable before the declaration, you will only get a variable of undefined

// Work fine, but don't! value; // => undefined var value;Copy the code

However, it can be used depending on where the function is defined:

// Greet ('World'); // => 'Hello, World! ' function greet(who) { return `Hello, ${who}! `; } // Greet ('Earth'); // => 'Hello, Earth! 'Copy the code

In general, we are not interested in the implementation of a function, but only in calling it. Therefore, it sometimes makes sense to call a function before defining it.

Interestingly, the import module has also been improved.

MyFunction (); import { myFunction } from './myModule';Copy the code

Of course, it is recommended to write import at the beginning of the file so that methods can be read and written.

4. Typeof behavior in TDZ

The Typeof operator is used to determine whether a variable is defined in the current scope.

For example, the variable notDefined is notDefined. Applying the Typeof operator to this variable does not raise an error:

typeof notDefined; // => 'undefined'
Copy the code

Because the variable is notDefined, the value of typeof notDefined is undefined.

But the Typeof operator behaves differently when used with variables in a temporary dead zone. In this case, JS throws an error:

typeof variable; // throws `ReferenceError`

let variable;
Copy the code

The reason behind this reference error is that you can determine statically (just by looking at the code) that the variable has been defined.

5. TDZ takes action in the current scope

Temporary dead zones affect variables in the scope in which the statement is declared.

Here’s an example:

Function doSomething(someVal) {// scope typeof variable; // undefined if (someVal) {// Internal block uses domain typeof variable; // throws `ReferenceError` let variable; } } doSomething(true);Copy the code

There are two scopes:

  • Function scope
  • Define the internal block scope of the let variable

In function scope, typeof variable evaluates to undefined. Here, the TDZ of the let variable statement has no effect.

Inside the scope, the Typeof variable statement uses a variable before the declaration, throwing an error. ReferenceError: ‘variable’ cannot be accessed before initialization, and TDZ only exists in this internal scope.

6. Summary

TDZ is an important concept that affects the availability of const, LET, and class statements. It does not allow variables to be used before declaration.

Conversely, when a var variable can be used before a declaration, it inherits older behavior and should be avoided.

In my opinion, TDZ is one of the good coding practices in the language specification.


The bugs that may exist after code deployment cannot be known in real time. In order to solve these bugs, I spent a lot of time on log debugging. Incidentally, I recommend a good BUG monitoring tool for youFundebug.

Original text: dmitripavlutin.com/javascript-…


communication

This article is updated every week, you can search wechat “big move the world” for the first time to read and urge more (one or two earlier than the blog hey), this article GitHub github.com/qq449245884… It has been included and sorted out a lot of my documents. Welcome Star and perfect. You can refer to the examination points for review in the interview.