JS核心运行机制-1.堆栈内存(ECStack.EC.GO.VO.AO)和函数底层处理机制

1,784 阅读4分钟

专有名词介绍:

ECStack:【Execution Context Stack】,执行环境栈;

EC:  【EC(G)】全局执行上下文,【EC(fn)】函数执行上下文。【EC(block)】块级执行上下文

VO:    【Variable Object】全局变量对象

AO: 【Active Object】活动变量对象

GO:【Global Object】全局对象

专有名词解析:

浏览器想要执行JS代码,需要提供一个供代码执行的环境,这个环境叫做ECStack---执行环境栈=>其实就是一块栈内存(从内存中分配出来的一块内存)。
在编程语言中,代码执行中,为了区分全局和函数执行所处的不同作用域(目的是为了区分每个词法作用域下代码的独立性)产生了=>EC(执行上下文)---(代码执行所在的词法作用域,或者代码执行所处的范围)。
EC(G)->global全局执行上下文,所有的代码都会在这个全局上下文中执行;

EC(xxx)函数执行上下文,函数的代码都会在这个上下文中执行;

在代码执行的时候EC(G)和EC(xxx)都会进栈(ECStack)执行。

在每一个执行上下文代码执行的时候都可能会创建变量的,所以在每一个上下文中(无论全局还是私有),都会有一个存储变量的空间:全局变量对象VO(Variable Object)和 函数活动变量对象AO(Active Object)他们是变量对象:存放当前上下文中变量的,只不过全局上下文中称为VO(G),私有上下文中称为AO(XX),但是也是变量对象。

浏览器在最开始加载代码的时候,不仅提供了一个栈内存供代码执行,而且还开始默认开辟了

一个堆内存,存储一些供JS调用内置的属性和方法都放在一个叫GO全局对象中,并且还会在全局变量对象中创建一个叫做window的变量指向这个GO堆内存,这也就是我们为什么可以通过window.xxx调用很多内置的方法;

 “在全局上下文中”,基于“var/function”声明的全局变量,也会给GO(window)中新增一个对应的私有属性,并且和全局的变量对象有“映射机制”:一个修改,另外一个也会跟着修改。
/* var a = 10; // 1.声明一个全局变量a=10   2.给window新增一个私有属性 window.a=10console.log(a); //首先看a是否为全局变量,如果是按照全局变量处理,如果不是全局变量,再看是否为window的一个属性,如果也不是window的属性则报错:a is not definedconsole.log(window.a); //直接访问对象的成员window.a = 20; //“映射机制” 全局变量a=20console.log(a); *//* // 基于“let/const”声明的全局变量和window没有关系let a = 10; //全局变量aconsole.log(a); //10console.log(window.a); //undefined */

下面来看一段代码的执行:

var a = {    n: 1};var b = a;a.x = a = {    n: 2};console.log(a.x);console.log(b); 

函数执行底层机制:

每当我们声明一个函数的时候,

1.都会创建一个堆内存和一个十六进制的地址,

2.把整个函数 的内部代码当做’字符串‘存储到堆中,并在堆内存中已经声明好了作用域(就是函数创建时的额执行上下文)

3.把地址存到栈中,供变量(函数名)调用。

注意:函数创建好了不执行,存储的就是一段字符串!

函数执行:

1.函数执行会创建一个栈内存EC(fn),并形成一个私有的上下文,创建一个AO用来存储当前函数私有上下文中的变量,

函数执行,会形成一个私有的上下文,保护里面的私有变量不受外界的干扰,我们把函数执行的这种保护机制称为’闭包‘----闭包作用之一’保护‘。

2.把上下文进栈执行

3.开始执行

  • 初始化作用域链[[]]
  • 初始化this
  • 初始化arguments
  • 形参赋值
  • 变量提升
  • diamante执行

4.一般情况下,函数执行完后,为了优化栈内存,会把形成的私有上下文出栈释放,这也就是谷歌浏览器的【GC垃圾回收机制】,

特殊情况:如果函数执行完后,所形成的私有上下文中,有一个东西(一般是引用类型的空间地址--函数或对象)呗当前上下文以外的事物所占用,那么当前上下文是不能被出栈释放的,上下文中的信息会保留下来,这也就是’闭包‘的另一种机制---保存机制;

来看一段函数代码的运行:

var x = [12, 23];function fn(y) {    y[0] = 100;    y = [100];    y[1] = 200;    console.log(y);}fn(x);console.log(x);