Before ES6, variables are declared using var, and there will be pre-parsing of variables (functions also have pre-parsing). I believe many of you will be confused by pre-parsing when learning JavaScript, although let and const were introduced in ES6, ES6 is not fully popularized at this stage, and many old codes are still written according to ES5 standards or even ES3 standards. Before ES6, variables are declared using var, and there will be pre-parsing of variables (functions also have pre-parsing). I believe many of you will be confused by pre-parsing when learning JavaScript, although let and const were introduced in ES6, ES6 is not fully popularized at this stage, and many old codes are still written according to ES5 standards or even ES3 standards.
01 display of variables and functions in memory
Similar to other languages, the variable types in JavaScript have basic data types and reference data types. Basic data types include undefined, null, boolean, String, and Number. The referenced data types are mainly objects (including {}, [],/^ $/, Date, and Function ).
var num = 24;var obj = {name:'iceman' , age:24};function func() { console.log('hello world');}
When a browser loads an html page, it first provides an environment for global JavaScript code execution, which is called global scope.
The basic data type is operated by value, and the referenced data type is operated by address.
Based on the above principles, the model of the above Code in the memory is:
Memory Model .png
The basic type is directly stored in the stack memory, while the object is stored in the heap memory, and the variable only holds the address of the object. So obj holds the address oxff44 of an object, and function func holds the address oxff66.
Execute the following code on the basis of the above Code:
console.log(func);console.log(func());
The first line outputs the definition of the entire function (the function itself ):
Row 2 code output result .png
Since the func function does not return a value, the output is undefined.
Note: What is written after return and what is returned by the function? If no return is returned, the default return value is undefined.
02 pre-resolution
With the above understanding of the memory model, we can better understand the pre-resolution mechanism. The so-called pre-resolution is: Before JavaScript code is executed in the current scope, the browser first declares or defines all variables with var AND function declarations by default.
2.1. Description and definition
var num = 24;
The simple code in this line is actually two steps: Declaration and definition.
Declaration: var num; tells the browser that there is a num variable in the global scope. If a variable is declared but not assigned a value, the default value is undefined.
Definition: num = 12; definition is to assign a value to the variable.
2.2 differences between the variables declared by var and the functions declared by function in pre-resolution
The variables declared by var are different from those declared by function during pre-resolution. The variables declared by var are declared in advance during pre-resolution, the function declared by the function will be declared in advance during pre-resolution and will be defined at the same time. That is to say, the difference between the variables declared by var and the functions declared by function is that they are not defined at the same time.
2.3. Pre-resolution only takes place under the current scope
At the beginning of the program, only the variables and functions in the window are pre-parsed. Only when the function is executed will the variable in the function be pre-parsed.
console.log(num);var num = 24;console.log(num);func(100 , 200); function func(num1 , num2) { var total = num1 + num2; console.log(total);}
Memory Model .png
03 scope chain
First, understand the following three concepts:
The scope in the function becomes a private scope, and the scope of the window is called a global scope;
The variables declared in the global scope are global variables;
The variables declared in the "private scope" and "function parameters" are both private variables;
In the private scope, when executing code, a variable is encountered. First, you need to determine whether it is a private variable. If it is a private variable, it has nothing to do with anything outside, if it is not private, search for the upper-level scope of the current scope. If the upper-level scope does not exist, continue searching until the window is located. This is the scope chain.
When the function is executed, a new private scope will be formed first, and then the execution will follow the steps below:
If a parameter exists, assign a value to the parameter first;
Pre-resolution in private scope;
Code in private scope is executed from top to bottom
Functions form a new private scope, which protects private variables from external interference (private variables cannot be modified outside, or private variables cannot be modified outside ), this is the concept of closure.
console.log(total); var total = 0;function func(num1, num2) { console.log(total); var total = num1 + num2; console.log(total);}func(100 , 200);console.log(total);
When the above code is executed, undefined (because of pre-resolution) will be output when total is output for the first time. When func (100,200) is executed, the content in the function body will be executed, in this case, the func function will form a new private scope. Follow the steps described above:
Assign values to parameters num1 and num2, respectively 100 and 200;
Code in func for pre-parsing;
Execute Code in func
Because pre-resolution is performed in the func function, the total variable in the func function is pre-parsed. When the total variable is output for the first time in the function, undefined is output, then assign a value to total, and 300 is output when total is output for the second time. Because the function body has the var declared variable total, the output total in the function body is not the total in the global scope.
In the last output of total, the output is 0. Here, the output is total in the global scope.
console.log(total); var total = 0;function func(num1, num2) { console.log(total); total = num1 + num2; console.log(total);}func(100 , 200);console.log(total);
After the code is slightly deformed, the total in the func function does not use var Declaration, so total is not private and will be searched for total in the global scope, that is to say, all total here is actually under the global scope.
04 differences between var and var in the global scope
Declared variables with var in the global scope can be pre-parsed, so no error will be reported before the value is assigned; When declaring variables without var, pre-parsing is not allowed, therefore, an error will be reported before the value assignment.
console.log(num1);var num1 = 12;console.log(num2);num2 = 12;
Problem: If a variable is not private in the private scope, the variable is searched for in the upper-level scope. If the upper-level variable does not exist, the variable continues to look up until the upper-level variable finds the window. If the upper-level variable does not exist, what if the window does not exist?
Value: console. log (total); --> error Uncaught ReferenceError: total is not defined
Set Value: total = 100; --> is equivalent to adding an attribute name total to the window, and the attribute value is 100.
function fn() { // console.log(total); // Uncaught ReferenceError: total is not defined total = 100;}fn();console.log(total);
Note: In JS, if the above Code reports an error without any special processing, the following code will no longer be executed
05 some abnormal mechanisms in pre-resolution
5.1 whether or not the conditions are true, you must make an early declaration with var.
if (!('num' in window)) { var num = 12;}console.log(num); // undefined
When JavaScript performs pre-parsing, all if conditions are ignored, because there is no block-level scope concept before es6. In this example, the num is pre-parsed, and the pre-resolution adds the variable to the window as an attribute of the window. Then, 'num' in window returns true. if this parameter is set to false, code execution does not enter the if block, and num is not assigned a value. log (num) output is undefined.
5.2 only pre-resolution "=" on the left, the right refers to, do not participate in pre-resolution
fn(); // -> undefined(); // Uncaught TypeError: fn is not a functionvar fn = function () { console.log('ok');}fn(); -> 'ok'function fn() { console.log('ok');}fn(); -> 'ok'
Suggestion: Try to use var fn =... When declaring a variable.
5.3 self-executed functions: defined and executed together
(function (num) { console.log(num);})(100);
The function defined by the autonomous function is not pre-parsed in the global scope. When the code is executed to this position, the definition and execution are completed together.
Supplement: other custom function execution methods
~ function (num) {}(100) + function (num) {}(100) - function (num) {}(100) ! function (num) {}(100)
5.4 The code in return will still be pre-parsed
function fn() { console.log(num); // -> undefined return function () { }; var num = 100; } fn();
The code below return in the function body is not executed, but requires pre-resolution. The code in return is our return value, so no pre-resolution is performed.
5.5 The name has already been declared. You do not need to declare it again, but you need to assign a value again.
var fn = 13; function fn() { console.log('ok'); } fn(); // Uncaught TypeError: fn is not a function
Typical questions
fn(); // -> 2 function fn() {console.log(1);} fn(); // -> 2 var fn = 10; // -> fn = 10 fn(); // -> 10() Uncaught TypeError: fn is not a function function fn() {console.log(2);} fn();
For more articles about pre-parsing in JavaScript, please follow the PHP Chinese website!