Variable promotion (thorough understanding required)

In the current scope (in the current execution context), all pre-declarations (create a variable) or definitions (assign a value to a variable) with var and all pre-declarations (create a variable) with function before all JS code executes. With the value of varA statement in advanceWith the functionPre-declaration + definition. The following snippet of code helps us understand this concept:

var getName = function () {
   console.log(4);
}

function getName() {
   console.log(5);
}

getName(); / / output 4
Copy the code

Why is getName() output 4 ❓ here we can analyze in two stages 😊 :

1. Before code execution: process statements with var and function keywords as follows:

  1. The pre-declaration of var defines a variable called getName,But no assignment, because this is before the code executes!
  2. Function predefines a variable called getName, but finds that the getName variable is already defined, so only a method is assigned to it. The getName = fuc = > 5

2, code execution: copy getName, getName= fuC =>4

Now that we understand this concept, let’s look at the next problem

function Foo() {
   getName = function () {
       console.log(1);
   }
   return this;
}

Foo.getName = function () {
   console.log(2);
}

Foo.prototype.getName = function () {
   console.log(3);
}

var getName = function () {
   console.log(4);
}

function getName() {
   console.log(5);
}

Foo.getName(); / / 2
getName(); / / 4
Foo().getName(); / / 1
getName(); / / 1
new Foo.getName(); / / 2
new Foo().getName(); / / 3
new new Foo().getName(); / / 3
Copy the code

Resolution:

Write tomorrow….. Have a headache 😫

Catch up with old friends for more than 2 hours, for the brothers’ lifelong event, I hold the heart 😂! This part will be made up tomorrow Saturday!

It’s so hard to get up on Saturday morning!!

Let’s move on. (ง • _ •) ง :

Based on the concept of variable promotion above, we know that variable promotion occurs before the code is run.

So step 1 (variable promotion) : look for the code for the function and var keywords

// first function Foo() {... }, function keyword, declaration + definition
Foo = AAAFFFOOO  // The AAAFFFOOO is assumed to be the Function object's reference address in the heap
Copy the code

Current memory map:

Var getName =... The var keyword is declared only
getName = undefined Var is only declared, not defined, so the value of getName is undefined
Copy the code

Current memory map:

// the second function getName() {... }, function keyword, declaration + definition. But it turns out that the getName variable was already declared in the previous step, so it just needs to be defined, that is, assigned
getName = func= >5 Func =>5 refers to the reference address of the method that prints 5 in the heap
Copy the code

At this point, the variable promotion is complete! We can see that the global getName currently points to func=>5

Current memory map:

2. Next step 2 (code execution) :Let’s take it line by line

< 1 sentence />


function Foo() {
   getName = function () {
       console.log(1);
   }
   return this;
}
Copy the code

The variable promotion stage has been completed and skipped. The current memory diagram is as follows:

< sentence 2 />


Foo.getName = function () {
   console.log(2);
}
Copy the code

Add the property getName to Foo, which is also a reference type, and the current memory map looks like this:

< sentence 3 />


Foo.prototype.getName = function () {
    console.log(3);
}
Copy the code

Add getName to Foo’s prototype, which is also a reference type, and the current memory map looks like this:

< sentence 4 />


var getName = function () {
    console.log(4);
}
Copy the code

Note !!!! This step is an assignment, because we are now in the method execution phase, not the variable promotion phase, so there must be no confusion here. Current memory map:

< sentence 5 />


function getName() {
    console.log(5);
}
Copy the code

The variable promotion stage has been completed, skipped, and the memory map remains unchanged, same as the previous step.

< sentence 6 />


Foo.getName();
Copy the code

From the method memory graph, it’s easy to see that the reference to foo. getName refers to a method with an output of 2, so the statement outputs the following:

2
Copy the code

< sentence 7 />


getName();
Copy the code

From the method memory diagram, it’s easy to see that the current global reference to the getName variable points to a method with an output of 4, so the statement outputs the following:

4
Copy the code

< sentence 8 />


Foo().getName();
Copy the code

Foo() is evaluated first according to JS operator execution priority, and Foo’s method execution stack (ECStack) is shown below:

Memory map at this time:

Foo() returns this, which is the Windows object, and window.getName(), which is the global getName method. The global getName refers to the method whose output is 1. So the statement outputs the following:

1
Copy the code

< sentence 9 />


getName();
Copy the code

GetName () {getName (); getName (); getName (); getName ();

1
Copy the code

< sentence 10 />


new Foo.getName(); / / 2
Copy the code

According to the execution priority of the JS operator, the highest priority is currently member access (… ……). GetName, which points to a method with an output of 2. The next highest priority is new(with argument list)(new… (…). ) operator, because the above code can be understood to split into the following two steps:

var s = Foo.getName;
var r = new s();
Copy the code

New a method, inside the method, as if it were a normal method, so this statement outputs:

2
Copy the code

< sentence 11 />


new Foo().getName();
Copy the code

The operator has the following precedence

1. new Foo() // as a whole XXX
2. xxx.getName()
Copy the code

GetName () = getName() = getName() = getName() = getName() = getName() And as we can see from our memory graph above, the reference refers to a method with an output of 3, so the statement outputs the following:

3
Copy the code

GetName = function(){Foo. GetName = function(){Foo. } is an attribute method defined for Foo, not an instance of Foo. To define a method for Foo, we usually write it like this:

var Foo = function(){
    this.getName=function(){... }}Copy the code

< sentence 12 />


new new Foo().getName();
Copy the code

The operator has the following precedence

1. new Foo() // as a whole XXX
2. xxx.getName // as a whole ZZZ
3. new zzz()
Copy the code

New Foo().getName is a method that hangs on the prototype object of an instance of Foo. The reference refers to a method whose output is 3.

3
Copy the code

conclusion

There are stack memory, object oriented, operator priority, prototype, closure and so on, so it is really a rocket interview, work screw, but these knowledge is not thoroughly mastered, can screw well?