current position:Home>On: Javascript variable pre declaration and scope promotion

On: Javascript variable pre declaration and scope promotion

2021-08-27 03:18:41 CccMan

keyword : Variable declarations 、 precompile 、 Scope 、 Strict mode

Variable declarations

stay JavaScript Creating variables in is often called " Statement " Variable , There are three ways to declare a variable , Include var、let And the direct assignment method that will be ignored by everyone .

A friendly reminder : The code below appears if you want to verify , Please use your browser to access about:blank page , Perform validation on a pure browser console copy , To prevent dirty web environment, some test variable names have been declared . image.png

var Keyword declaration variable

We use var Keywords to declare variables :

var a;
 Copy code 

After variable declaration , The variable is empty (undefined). To assign a value to a variable , Please use the variable assignment symbol ( Equal sign ):

var a;
a = 'var_a';
 Copy code 

One more word here , If the assignment is undefined, This is no different from not assigning values :

var alm = undefined

Of course we can use it var Keyword declares a variable and assigns it a value , like this :

var a = 'var_a';
 Copy code 

Null variable declaration

That's it var Variable declaration method , Let's put let The variable declaration method will not be mentioned first , Let's start with the preface Variable declaration of direct assignment . seeing the name of a thing one thinks of its function , The variable declaration of direct assignment is direct assignment , Instead of using var and let keyword , Let's call it Null variable declaration Well , Similar to the following code :

a = 'a'
 Copy code 

You may see such code , You'll have questions , Didn't you say variable declaration ? There is no statement written here , Don't you just assign a value to a variable ?! Yes , You're right , The above code is variable assignment in most cases , But only variables a Where it has been stated . Strictly speaking , It should be called : In the current and above scopes , Variable a declared

Scope

I have to talk about the concept of scope first , Scope is basically the standard configuration of all programming languages ,JavaScript No exception . There is no scope distinction , You can imagine how messy the code we write , We have to be careful whether the variables we declare have been declared , Worry that the newly declared variable cannot declare or overwrite the declared variable with the same name , Lead to all kinds of unpredictable problems .

Scope can be divided into global scope and local scope , A global scope is an area accessible to all local scopes . The current scope can access all declared variables and functions in the current and parent scopes , Cannot access any variables and functions in the child scope .

The global scope of the browser environment

We all know that browsers are JavaScript The most common running environment for code , If we're in the browser devtools( Developer tools ) Written directly in the console js Code , That's actually provided by a browser JavaScript Global scope . We're in there direct All variables declared ( It does not include the use to be described later let Variables declared by keywords ), It's all in window A new attribute has been added to the object . We can verify it , Use var Keyword declare a variable :

var a = 'var_a'
console.log(a) // var_a
console.log(window.a) // var_a
console.log(window.a === a) // true
 Copy code 

A local scope can have a parent scope ( One or more levels ) And child scopes ( One or more levels ), Therefore, the global scope can also be understood as a root scope , It is the top-level parent scope of all local scopes . forehead .. It seems a little complicated , It's very simple , Draw a picture at a glance !

Global scope
Local scope 1
Local scope 2
Local scope 3
Local scope 4
Local scope 5
Local scope 6

The tree above can be used to describe JavaScript The relationship between the various scopes of , The global scope is the root node of the tree , Local scope 6 Of Current and above scopes Include : Local scope 6、 Local scope 5、 Local scope 2 And global scope . If we are in local scope 6 A statement in the above scope is Has not declared The variable of , that JavaScript For our global scope Top Declare a new variable , The code is as follows :

// console.log(a); // a is not defined

function f1() {
    var a = 'f2_a'
}

function f2() {
    function f4() {
        var a = 'f4_a'
    }

    function f5() {
        function f6() {
            a = 'f6_a'
            console.log(a); // f6_a
        }
        f6()
    }

    f4()
    f5()
}

function f3() {
}

f1();
f2();
console.log(a); // f6_a
 Copy code 

Explain the code above , If we directly input and execute the above code on the browser console , It is as like as two peas .f6 The function body is the scope in the graph 6, We are f6 Give a variable directly in a assignment 'f6_a'. You can see that in the code, except f6 There are variables in the scope a outside , stay f1 and f4 Variables are declared and assigned in a, But the function f6 and In the global scope console.log(a) The output is f6 The value given in , This means that f6 Although only variables are given in a The assignment operation is carried out , but JavaScript But a new variable is declared under the global scope a, And then in f6 When the function is executed, it is assigned to 'f6_a'.

JavaScript Variable pre declaration and variable scope promotion

Careful friends may have seen , In the first line of the above code, I annotated a line of code , The following comments indicate the execution result if this line is released , There's nothing wrong with you , If this line of code executes , The browser environment will because the variable cannot be found a And throw an exception . Why is that ? You didn't just say JavaScript A new variable will be declared under the global scope a Do you , Why can't you find it here a?

Actually , This involves JavaScript A design of language , Precompiling mechanism . What is? precompile , We all know JavaScript It's a scripting language , The characteristic of scripting language is interpretation and execution , Let the code interpret and execute in sequence line by line . however JavaScript It's a little different , It's really executing js Before the code , We'll first see if there are... Under the current scope var Variables declared by keywords or directly assigned without any keywords ( Variables that have not been declared in the current and above scopes ), If so, you will declare these variable names in advance , So where to declare ? This makes a difference , about var Key words , The accessible scope of the variable will only be promoted to the current scope Top , For directly assigned variables ,JavaScript It will be promoted to the global scope .

Strictly speaking , It shouldn't be called precompiling , In other words “ Pre explanation ” Maybe more appropriate , After all JavaScript It is not a compiled language in essence .

Here is an emphasis on , The time to raise the accessible range of a variable is when the code has been executed in this scope , If not, there will be no behavior of variable accessible range Promotion . Now look at the code above , It's clear , Because the first line of code is in the global scope , At this time, the code has not been executed to f6 Scope , therefore f6 Variables in scope a Variable accessible range promotion has not been performed yet , So there are no variables in the global scope a This statement . That's to say. , If we declare a variable on the second line of the global scope a, Won't you report an error on the first line ? Yes ! If you don't believe it, try the following code ( Please refresh the web environment and execute on the console ):

console.log(a); // undefined
var a = 'global_a'
console.log(a); // global_a
 Copy code 

Let's try the variable promotion with direct assignment :

console.log(a); // a is not defined
a = 'global_a'
console.log(a); // global_a
 Copy code 

It's over. The car overturned , Doesn't it mean that directly assigned variables will be promoted to the global , This is why the variable cannot be found in the first line of the global scope a?! Yes, it's really stupid ... Directly assigned variable promotion does not occur in the precompile phase , It is only promoted when the code is executed to the corresponding line ! So there are two different situations :

// console.log(a); // a is not defined
function f1() {
    console.log(a); // a is not defined
}

f1();
a = 'global_a'
console.log(a);
 Copy code 
// console.log(a); // a is not defined
function f1() {
    console.log(a); // global_a
}

a = 'global_a'
f1();
console.log(a); // global_a
 Copy code 

Let's look at the previous example , If we were f1 In advance (f1 The function executes first ) Put variables a Promote to global , Then the code executes in turn f1、console.log(a)、f2()、f4()、f5()、f6(), When executed f6 The assignment statement is encountered again a = 'f6_a' here ,JavaScript There will be no more variable Promotion , Because the whole situation already has a name a Of variables , So here is a pure global variable assignment operation .

// console.log(a); // a is not defined

function f1() {
    //  Variable  a  Promote to global 
    a = 'f1_a'
    console.log(a);// f1_a
}

function f2() {
    function f4() {
        var a = 'f4_a'
    }

    function f5() {
        function f6() {
            //  No more variable Promotion , because  f1  Has been promoted once 
            a = 'f6_a'
            console.log(a); // f6_a
        }
        f6()
    }

    f4()
    f5()
}

function f3() {
}

f1();
console.log(a); // f1_a
f2();
console.log(a); // f6_a
 Copy code 

ok, We understand the above complex situation , Then the following situation is a piece of cake , Let's practice :

var a ='var_a'
function fn(){
    a = 'fn_a'
    console.log(a); // fn_a
}

fn();
console.log(a); // fn_a
 Copy code 

How the above code is JavaScript Explain the operation ? According to the theory we analyzed above , First, the global precompiling stage , from var Declared variables a Will be promoted to the current scope, that is, the top of the global scope is declared in advance . When the first line of code is executed , Variable a To be an assignment 'var_a', When fn When it is about to be executed , Also, precompile first , Encountered another variable a, But found a Has been declared in the upper scope , So the third line is a assignment , It will only be considered as an assignment statement , And not again Variable pre declaration and Variable scope promotion operation . So the answer is clear , After the code is executed, it will output twice fn_a.

let、const Keyword declaration variable

Now you know JavaScript How bad is the variable declaration in ! Use var Key words declare variables very carefully ! So in es6 in , It is not recommended to use var key word , While using let and const key word ! These two keywords are only used in es6 Only in grammar can ( No Support es6 Syntax browser Out of commission ), In usage let Keywords declare variables and var Do not have what difference :

let a = 'let_a';
 Copy code 

and const Declared variables cannot be modified again , The variable must be assigned a value at the time of declaration , Otherwise, it will throw the exception , as follows :

const a; // Uncaught SyntaxError: Missing initializer in const declaration
 Copy code 

let The emergence of keywords is to prevent the above-mentioned due to JavaScript Precompiling and variable promotion features cause all kinds of inexplicable problems . Use let Declared variables do not Variable pre declaration and Scope promotion

however , Let's take a look at the following code , You'll find something new ...

let a = 'let_a'
console.log(a) // let_a
console.log(window.a) // undefined
 Copy code 

You're not mistaken , adopt let Declared variables a Not mounted to global object window On , Why is that ? Don't window Isn't the object internal global scope ?

Actually in es6 in , Added let and const Two variables declare keywords other than , The concept of block level scope is also added . What is a block ? A pair of braces “{}” The area within is actually a code block , Such as if、for And so on ,let and const The scope of the keyword is within this block , The declared variable cannot be accessed outside the scope of the specified block .

So the local scope mentioned above , Strictly speaking, it should be the function scope , The real local scope includes function scope and block scope . therefore , The following code execution results can be understood .

function fn() {
    {
        // console.log(a)// Cannot access 'a' before initialization
        let a = 'let_a'
        console.log(a) // let_a
    }
    console.log(a) // a is not defined
}

fn()
 Copy code 

Strict mode

In order to prevent developers from using var Keywords to declare variables without knowing , Cause possible abnormal conditions .es6 Strict patterns are provided to restrict developers , Use... In different scopes "use strict"; You can make this scope a scope of strict mode , as follows :

"use strict";
fn();

function fn() {
    a = 'fn_a' // a is not defined
}
 Copy code 

With strict pattern constraints , The variables above a Never again Variable pre declaration and Scope promotion 了 , But you will find fn The function declaration will still be pre declared ( Otherwise, the code execution in the second line should report fn is not defined abnormal ), Ha ha, magical JavaScript!

summary

OK, That's about JavaScript All the contents of variable pre declaration and scope Promotion , Here's a summary ,JavaScript When interpreting and executing code , Precompiling will be performed under the current scope first . In the precompile phase, all the users in the current scope will be found first var Variables declared by keywords , The variable declaration operation will be performed immediately at the top of the current scope . In the code interpretation execution phase , When it is found that a direct assignment statement needs to be executed , And the name of the variable to be assigned Never stated before ,JavaScript A variable with the corresponding name will be declared immediately at the top of the global scope , And then assign the value ! The flow chart is as follows :

Precompile phase
find var key word
Variables declared at the top of the current scope
Code interpretation execution phase
Direct assignment + Never declared
Variables are declared at the top of the global scope
Variable assignment

Statement : The above analysis results are only obtained through personal test and analysis , If there is any mistake or unclear description, please criticize and correct ! I'm a beginner , Yes JavaScript I don't know much about , For example, the errors in the article mislead and trouble you , Please forgive me a lot ! Please let us know in time , I will correct the relevant contents in time ~

Reference article

  1. In depth understanding of JavaScript Scope and scope chain

copyright notice
author[CccMan],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2021/08/20210827031833103Z.html

Random recommended