当前位置:网站首页>JS stack memory

JS stack memory

2022-06-24 01:00:00 ruochen

1. Basic stack memory evaluation

The output of the following question is ?

let a = {
  n : 1
}
let b = a
a.x = a = {
  n: 2
}
console.log(a.x)  // undefined
console.log(b)  // { n: 1, x: { n: 2 } }

Perform process analysis :

  1. a = {n: 1}, First create an address in heap memory ( such as :AAAFFF00), The content is n: 1, Then in the global execution context EC(G) Global variables environment in VO(G), Create global variables a, Point to the heap memory address :AAAFFF00
  2. b = a, Empathy , In the global variable environment VO(G) Create a global variable b, Point to the heap memory address :AAAFFF00
  3. a.x = a = { n: 2 }, Priority of this , In fact, it is equivalent to a.x = {n: 1},a = {n: 1}
  4. a.x = {n: 1}, Create another address in heap memory ( such as :AAAFFF11), The content is n: 1, stay a Memory address of AAFF00 Create a x Variable , Point to AAAFFF11, here ,b = a = {n:1, x: {n: 1}}
  5. a = {n: 1}, take a Is directed by AAAFFF00 Change it to AAAFFF11

So the end result is :

b = {n:1, x: {n: 1}}

a = {n: 1}

2. Abnormal variable elevation

Variable Promotion : Before the current context executes , Will be able to var/function Declare or define promotion , belt var Only declare , belt function Statement of + Definition

But if you meet {} Block level scope , New and old browsers behave differently ( compatible ES3、 compatible ES6)

  • IE browser <=IE10( The old version )undefined No matter {}, As always function Statement + Definition , And there will be no block level scope
  • New version of browser ( there {} Is divided by... In the object {})undefined{} Medium function, In the global context, only declare that it is no longer defined ;undefined{} It appears that function/let/const, A block level scope will be created

Let's take a question to illustrate :

var a = 0
if(true) {
  a = 1
  function a() {}
  a = 21
  console.log(a)  // 21
}
console.log(a) // 1

If it's in IE10 following Implementation process of :

  1. Variable Promotion function a() {}
  2. Global variable promotion var a
  3. Start execution , overall situation a = 0
  4. overall situation a = 1
  5. overall situation a = 21
  6. Print global a: 21
  7. Print global a: 21

If you are in a new version of the browser , That is, forward compatibility ES3, Backward compatibility ES6 Implementation process of :

  1. Because the variables go up , therefore var a,function a In the global execution context EC(G) Global variables environment in VO(G) Create a global variable in a
  2. Code execution a = 0, Global variable environment VO(G) in a = 0
  3. encounter {} Block level scope , Generate a block level execution context EC(block), Will generate a private variable object AO(block)
  4. In this block-level scope , Because there is function a, So variable promotion occurs at the block level , Statement + Definition , stay heap Generate a function in heap memory , stay AO(block) Create a variable a Point to function heap memory , After that, in this level , Encountered a It's all private

image.png

  1. Block level a = 1,AO(block) in a = 1

image.png

  1. encounter function a() {}, Because this function , For forward compatibility ES3, Therefore, it has been promoted once in the overall situation ; For backward compatibility ES6, Promote again in the block level scope , therefore Browsers for compatibility , When you really encounter a function at the block level , It will do one thing : Before encountering this code , Will put the code before all the right a The operation of , Map to a global , But the latter will not be dealt with , It will think that everything after this is private , Before a = 1 Will be mapped to the global VO(G) in a =1

image.png

  1. after a = 21, It is already private , So only block level is affected AO(block) in a = 21

image.png

  1. In block level console.log(a) => AO(block) a => 21
  2. Global console.log(a) => VO(G) a => 1

Extended exercises

To deepen this perverse rule , Let's do a few more questions :

Abnormal lifting exercises 1

{
  function foo() {}
  foo = 1
}
console.log(foo);
  • The first 1 Step :{} Medium function foo In variable Promotion , Declare only in global , Does not define
EC(G):  
   AO(G) function foo
  • The first 2 Step , stay {} There are... In the block level function, So a block level scope will be generated EC(Block),foo In this block level scope , Variable Promotion : Statement + Definition
EC(block):   
   AO(block): funciont foo() {}
  • The first 3 Step , Start execution ( After the execution process ,AO The variable object =>VO Activate the object ), because foo Both global and private are declared , For compatibility ES3 and ES6, In carrying out the function foo() {} in , The previous operations are mapped to the global , That is to say AO(block): funciont foo() {} Statement + The process of definition
EC(G):  
   VO(G) function foo() {}
  • The first 4 Step , perform foo = 1, Because there are... In the block level scope foo Private variables , So it's in EC(block) Assignment in
EC(block):
      VO(G) foo => 1

Abnormal lifting exercises 2

Now I will start to be lazy , Ha ha ha , Please understand the following annotation steps according to the context

//  The first 1 Step ,EC(G), AO(G): function foo
//  The first 2 Step ,EC(block), AO(block): foo => function foo() {}
//  The first 3 Step , Start execution ,EC(G), VO(G): foo => function foo() {}
//  The first 4 Step ,foo = 1, EC(block), VO(block): foo => 1
//  The first 5 Step ,EC(G), VO(G): foo => 1
{
  function foo() {}
  foo = 1
  function foo() {} // 1
}
console.log(foo); // 1

Abnormal lifting exercises 2

//  The first 1 Step ,EC(G), AO(G): function foo
//  The first 2 Step ,EC(block), AO(block): foo => function foo() {}
//  The first 3 Step , Start execution function foo() {},EC(G), VO(G): foo => function foo() {}
//  The first 4 Step ,foo = 1, EC(block), VO(block): foo => 1
//  The first 5 Step ,function foo() {} => EC(G), VO(G): foo => 1
//  The first 6 Step ,foo = 2,EC(block), VO(block): foo => 2
{
  function foo() {}
  foo = 1
  function foo() {}
  foo = 2
  console.log(foo); // 2
}
console.log(foo); // 1

3. Stack memory with formal parameters

The output of the following function is ?

var x = 1
function func(x, y = function func2() { x = 2 }) {
  x = 3;
  y()
  console.log(x)  // 2
}
func(5)
console.log(x)  // 1

Let's use the diagram to analyze the process :

  1. Global execution x = 1, stay EC(G) Create a VO(G), Create values 1, Create another object x,x Point value 1

image.png

  1. Found function declaration , Create a heap memory for it , Define its functions , In this memory , Declare its scope , The global scope VC(G), Shape parameter x、y, And its function body string , And create a func, Point to this heap memory

image.png

  1. perform func(5), Execute a function , A private execution context will be created for it EC(func), A private variable environment will be created in it AO(func)
  2. stay EC(func) Initial its scope chain : Its own scope EC(func) And its parent scope EC(G)( Global scope )
  3. Parameter assignment : Yes x = 5,y No ginseng , So use its default value function func2, Encounter a function , Apply heap memory for it AAAFFF111, Again , Analyze its scope and formal parameters , And save the function body to memory , And will y Point to AAAFFF111

image.png

  1. After analyzing the relationship , Start execution func5 The body of the function
  2. x = 3, In your own scope EC(func) Search for x, Found private x, So will x Point to 3
  3. y(), In your own scope EC(func) Search for y, Found to have y Point to func2, Execute function func2, And it creates a separate execution context EC(func2), Analyze the scope chain for it , Own scope EC(func2) And its parent scope EC(func), Because it has no formal parameter assignment , Therefore, no private variables are created

image.png

  1. Start function func2 Function body ,x = 2, So in its own scope EC(func2) The variable cannot be found in x, Will report to its parent scope EC(func) Search for , Found to have x, So will EC(func) in x Point to 2

image.png

  1. func2 end of execution , Carry on EC(func) Medium console.log(x), Output its own x:2
  2. func end of execution , Carry on EC(G) Medium console.log(x), Output Global VO(G) Medium x:1

image.png

4. Abnormal version of stack memory with formal parameter function

The output of the following topic is ?

var x = 1
function func(x, y = function func2() { x = 2 }) {
  //  here ,x More than a var Statement 
  var x = 3;
  y()
  console.log(x)  
}
func(5)
console.log(x)

Here we will talk about the browser running es6 The mechanism of the :

ES6 There are two cases where block level scopes are generated

The first 1 Kind of , natural {} The resulting block level scope

This is what we usually know ,ES6 There is a block-level scope in , As long as {}( Except for the {}) appear let/const/function

The first 2 Kind of , It is generated by the browser at runtime , That is, as long as the following two conditions are met :
  1. Function has a default value assigned to any formal parameter
  2. A variable has been declared separately in the function body (var/let/const/function All count )undefined Then this function will produce 2 Context (s)
*  One is the private context generated by the execution of the function itself , For example, above `func` Function execution time , Will generate `EC(FUNC)`
*  One is the block level context enclosed by function body braces `EC(BLOCK)`

below , We still draw pictures to analyze :

  1. First process , And the last question 1\2 The steps are consistent , The global execution context is still generated EC(G), It's in VO(G) Declare two variables :x and func,x Point value 1,func Point to function heap memory AAAFFF000

image.png

  1. Second process , perform func(5), At this time , because func Mesomorphic parameter y Set default value , And the variable... Is declared in the function body var x = 3, According to the above rules , Two execution contexts are generated here EC(FUNC) and EC(BLOCK)
  2. Let's analyze it first EC(FUNC) , Its scope is EC(G), The scope chain is its own context EC(FUNC) And the parent scope context EC(G), Its formal parameter is x => 5,y => function func2 Heap memory AAAFFF111

image.png

4. Yes EC(BLOCK) Code block analysis , Its scope is EC(FUNC), The scope chain is its own context EC(BLOCK) And the superior execution context EC(FUNC), At the block level ,`var

x = 3 It states x, therefore x Is a private variable in the block level scope , When executed x = 3 when , In the block level x => 3`

image.png

  1. Carry on y(), No... Found in block level y Variable , Go to its scope chain superior EC(FUNC) look for , eureka y, perform y(), Generate func2 Execution context EC(FUNC2), Its scope is EC(FUNC), So the scope chain is [ Own execution context EC(FUNC2), Scope EC(FUNC)], No formal parameter and variable declarations , So there is no own private variable ; Execute the inner function body x = 2, stay EC(FUNC2) I can't find it in China. x, So go to its scope superior to find EC(FUNC),EC(FUNC) There is x, So will EC(FUNC) in x => 2

image.png

  1. EC(BLOCK) Carry on console.log(x), Print is EC(BLOCK) In private x, namely 3
  2. func(5) completion of enforcement , Continue to EC(G) in console.log(x), Print is VO(G) Medium x, namely 1

image.png

therefore , The answer is 3 and 1

below , To prove that I'm not talking nonsense ='=, We debug the last question on the browser

  1. Make a breakpoint at the beginning debugger, Open in browser , because window Too many global variables , It's hard to find the overall situation VO(G) Of x, So I am Watch Added in window.x Variable , It's convenient for us to observe VO(G) in ( That's the browser's Global)x Value , You can see , Before debugging , In the overall situation x yes undefind
//  The first 4 topic : Abnormal stack evaluation with formal parameters 
debugger;
var x = 1
function func(x, y = function func2() { x = 2 }) {
  var x = 3;
  y()
  console.log(x)
}
func(5)
console.log(x)

image.png

  1. When performing the x=1 when ,func(5) Before execution , You can see the overall situation VO(G) Of x = 1

image.png

  1. So let's keep going func(5), You can see the birth Scope in , That is to say EC(FUNC) In the scope of , Generate two execution contexts BLOCK and LOCAL, Corresponding to what we said above EC(BLOCK) and EC(FUNC), Because there are... In the private variables x, Then there are declarations at the block level x, So it will be private x Map to... In the block level x

image.png

  1. Execute block level var x = 3, Find private variables in the block level x Turn into 3

image.png

  1. perform y(), Generation func2 Execution context EC(FUNC2), Because there are no private variables , So its Local It's empty

image.png

  1. After execution y() in x = 2 after , notice EC(FUNC) Medium x => 2

image.png

  1. perform EC(BLOCK) in console.log(x), The output is Block Medium x

image.png

  1. perform EC(G) in console.log(x), The output is Global Medium x

image.png

thus , The above analysis conclusion is verified .

原网站

版权声明
本文为[ruochen]所创,转载请带上原文链接,感谢
https://yzsam.com/2021/11/20211121160438048j.html