For JavaScript concepts, review the past to learn new.

Concept: What is Hositing

In JavaScript, ReferenceError occurs if you try to use an undeclared variable. After all, variables are not declared, so JavaScript cannot find them. With declarations of variables, it works fine:

console.log(a);
// Uncaught ReferenceError: a is not defined
Copy the code
var a;
console.log(a); // undefined
Copy the code

Consider writing like this:

console.log(a); // undefined
var a;
Copy the code

Intuitively, programs are executed line by line from top to bottom. Using an undeclared variable, a, should result in ReferenceError, but instead prints undefined. This phenomenon is called collieries. Var A has been “moved” to the top for some reason. It can be understood as the following form:

var a;
console.log(a); // undefined
Copy the code

Note:

  1. The position of the declaration in the code actually doesn’t change.

  2. As is only for claims, assignment doesn’t.

    console.log(a); // undefined
    var a = 2015;
    
    // Take the following form
    var a;
    console.log(a); // undefined
    a = 2015;
    Copy the code

    Var a = 2015 var a = 2015

  3. Function expressions do not apply.

    fn(); // TypeError: fn is not a function
    var fn = function () {}
    
    // Take the following form
    var fn;
    fn();
    fn = function () {};
    Copy the code

    Here a function call by fn() on undefined results in an illegal operation and therefore raises TypeError.

  4. In the case of function and variable declarations, the reactive power will apply as follows:

    console.log(fn);
    var fn;
    function fn() {}
    
    // Take the following form
    function fn() {}
    var fn; // Duplicate declarations will be ignored
    console.log(fn);
    Copy the code

For functions with arguments:

fn(2016);

function fn(a) {
    console.log(a); / / 2016
    var a = 2015;
}

// Take the following form
function fn(a) {
    var a = 2016; // The value is the value passed in when the function is called
    var a; // Duplicate declarations will be ignored
    console.log(a);
    a = 2015;
}
fn(2016);
Copy the code

In summary, it’s understandable that collieries is a process of processing all claims. It is important to note that assignment and function expressions do not reactorize.

Significance: Why need collieries

Can handle scenarios where functions call each other:

function fn1(n) {
    if (n > 0) fn2(n);
}

function fn2(n) {
    console.log(n);
    fn1(n - 1);
}

fn1(6);
Copy the code

In the case of line-by-line execution, there must be a sequential order, such as a reciprocal call between FN1 and FN2, that will not work properly without the reachareas.

Specification: operation rules of reactive power

For details, see the ECMAScript 2019 Language Specification. Related to reactive is at 8.3 Execution Contexts.

Understanding Execution Context and Execution Stack in Javascript

See the examples below:

var a = 20;
var b = 40;
let c = 60;

function foo(d, e) {
    var f = 80;
    
    return d + e + f;
}

c = foo(a, b);
Copy the code

Create an Execution Context like this:

GlobalExecutionContext = {
  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Object".c: < uninitialized >,
      foo: < func >
    }
    outer: <null>,
    ThisBinding: <Global Object>
  },
  VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Object",
      // Identifier bindings go here
      a: undefined,
      b: undefined,
    }
    outer: <null>, 
    ThisBinding: <Global Object>
  }
}
Copy the code

At run time, variable assignment is complete. So GlobalExecutionContext at execution time looks something like this:

GlobalExecutionContext = {
  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Object".c: 60.foo: < func >,
    }
    outer: <null>,
    ThisBinding: <Global Object>
  },
  VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Object",
      // Identifier bindings go here
      a: 20,
      b: 40,
    }
    outer: <null>, 
    ThisBinding: <Global Object>
  }
}
Copy the code

When a call to function foo(a, b) is encountered, a new FunctionExecutionContext is created and executes the code in the function. In the creation phase it looks like this:

FunctionExecutionContext = {
  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative".Arguments: {0: 20.1: 40.length: 2}},outer: <GlobalLexicalEnvironment>,
    ThisBinding: <Global Object or undefined>,
  },
  VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative",
      f: undefined
    },
    outer: <GlobalLexicalEnvironment>,
    ThisBinding: <Global Object or undefined>,
  }
}
Copy the code

When executed, it looks like this:

FunctionExecutionContext = {
  LexicalEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative".Arguments: {0: 20.1: 40.length: 2}},outer: <GlobalLexicalEnvironment>,
    ThisBinding: <Global Object or undefined>,
  },
  VariableEnvironment: {
    EnvironmentRecord: {
      Type: "Declarative",
      f: 80
    },
    outer: <GlobalLexicalEnvironment>,
    ThisBinding: <Global Object or undefined>,
  }
}
Copy the code

After the function completes, the return value is stored in C. So GlobalExecutionContext is updated. After this, the code execution is complete and the program is terminated.

Details: var, let, and const differences in reactive power

Reworking the specification: As a reactor-based operation rule, notice that in the creation phase, whether using let, const, or VAR, the reactor-based operation will occur. The difference is that let and const declarations are set to uninitialized, while var is set to undefined. ReferenceError Cannot access ‘c’ before initialization is thrown when a variable declared by let or const. The noun is Temporal Dead Zone.

function demo1() {
    console.log(c); // c's TDZ start
    let c = 10; // end of c TDZ
}
demo1();

function demo2() {
    console.log('begin'); // c's TDZ start
    let c; // end of c TDZ
    console.log(c);
    c = 10;
    console.log(c);
}
demo2();
Copy the code

conclusion

Really is a review of the new, found that they know how little. Beat yourself up. Follow up on this, Prototype, closures, scope, etc.

The resources

  1. I know you know how much, but how much?
  2. MDN: Hoisting
  3. You-Dont-Know-JS 2nd-ed
  4. ECMAScript 2019 Language Specification
  5. Understanding Execution Context and Execution Stack in Javascript
  6. JavaScript advanced programming