I wrote earlier: juejin.cn/post/684490… Looking back now, I feel I could have gone further. Creating a variable in JS is a three-step process,

  1. statement
  2. Initialize the
  3. The assignment

The surface properties

  1. Variables declared by let const cannot be promoted. Variables declared by var are promoted
  2. Let const cannot be declared repeatedly. Var can
  3. Const variables cannot be changed. If an object is declared, the value inside the object can be changed

Specific point again

  1. Var is created and initialized at the same time, and the initialized value is undefined
  2. Let const is created first and initialized at the assignment step, so accessing this variable without initialization throws an error
  3. Const cannot be modified because of JS engine when accessing the variable will go to visit this memory address first, then go to access memory space, and finally get the content in the memory space, if is the assignment operation, also only has opened up a new memory space, and then bind their relationship, and the old memory space by the GC recycles it, The memory address declared by const is bound to an immutable relationship with the memory space
  4. The let in the body of the loop is because each time a new variable is created, it can be understood as forming a separate closure

Performance under Babel

We first have to install the environment, if the situation has been stuck, it is recommended to stand in the window to look out for 5 minutes, come back

npm install babel-loader -DCopy the code

npm install @babel/core @babel/preset-env @babel/plugin-transform-runtime -DCopy the code

npm install @babel/runtime @babel/runtime-corejs3Copy the code

Modify the configuration in WebPack

let path = require('path')

module.exports = {
    mode: 'development',
    entry: './src/index.js',
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ["@babel/preset-env"],
                        plugins: [
                            [
                                "@babel/plugin-transform-runtime",
                                {
                                    "corejs": 3
                                }
                            ]
                        ]
                    }
                },
                exclude: /node_modules/
            }
        ]
    }
}Copy the code

A simple example

{
    let a = 1
}
console.log(a);Copy the code

Compiled code:

{ 
    var _a = 1; 
} 
console.log(a);Copy the code

Let /const each {} is an independent scope. The outside can’t access the inside, but the inside can access the outside

Classic Interview questions

var funcArr = [];
for (let i = 0; i < 3; i++) {
    funcArr[i] = function () {
        console.log(i);
    };
}
funcArr[0]();Copy the code

What it looks like after compilation:

var funcArr = [];
var _loop = function _loop(i) {
    funcArr[i] = function () {
        console.log(i);
    };
};
for (var i = 0; i < 3; i++) {
    _loop(i);
}
funcArr[0]();Copy the code

You can see that the original for loop has been split into two parts, which should make sense, but the only detail is

var _loop = function _loop(i) {}Copy the code

Function (_loop) is ignored, so setTimeout is used to pass a value.

SetTimeout version

for (var i = 0; i < 3; i++) {
    setTimeout(() => {
        console.log(i);
    });
}Copy the code

The compiled:

for (var i = 0; i < 3; i++) {
    (function() { console.log(i); })}Copy the code

After compiling the code is generated a “malformed” immediately execute the function, because I save part of the irrelevant code ~ interested students can copy the code to try

What about let?

for (let i = 0; i < 3; i++) {
    setTimeout(() => {
        console.log(i);
    });
}Copy the code

The compiled:

var _loop = function _loop(i) {
    (function() { console.log(i); })};for (var i = 0; i < 3; i++) {
    _loop(i);
}Copy the code

If we manually add a parenthesized executor, the result will be the same as if we had used let, so IIFE is the best idea in the world