详细解读函数的底层处理机制

2021-07-28  本文已影响0人  小生菜呢

JS中的堆(Heap)栈(Stack)内存

都是在计算机内存中开辟的空间
EC(Execution [ˌeksɪˈkjuːʃn] Context )执行上下文:区分代码执行的环境
  1. 全局上下文EC(G)
    2.函数私有上下文EC(?)
    3.块级私有上下文EC(Bolck)

GO(Global Object)全局对象

let 变量 = 值 的操作步骤

  1. 对象类型值:按照堆内存地址来操作
    @1、对象:开辟一个堆内存空间(16进制地址)、一次存储对此昂的键值对、把空间地址赋值给变量
    @2、函数:内存空间存储三部分信息
    作用域[[scope]]:当前所处上下文
    函数体中的代码字符串
    当作普通对象存储的静态属性和方法[name&length]

以代码为例来详细解读函数的底层处理机制

1 、

var x = 12
let y = 12
z = 14
console.log(x)
console.log(window.x)
console.log(y)
console.log(window.y)
console.log(z)
console.log(window.z)

全局代码执行,形成EC(G)全局执行上下文

@5、console.log(z):结果是14;直接去GO中找
@6、console.log(window.z) :结果是14;直接去GO中找
2、

let x = [12,23]
function fn(y) {
  y[0] = 100
  y = [100]
  y[1] = 200
  console.log(y)
}
fn(x)
console.log(x)
image.png
文字版:

再重复一边

代码执行步骤:
1、浏览器开辟一块空间-->栈内存-->ECStack代码执行环境栈
2、浏览器开辟一块空间-->堆内存-->-GO全局对象:16进制地址定为 0x000
@1、存放内置属性:
setTimeout,
setInterval,
requestAnimationFrame
.......
3、最开始肯定是全局代码执行,形成EC(G):全局执行上下文-->进栈执行
@1、全局执行上下文中,基于let/const声明的变量要存放到全部变量对象VO(G)中
4、代码自上而下执行
5、[12,23]是个数组,所以开辟一个堆内存来存储,16进制地址暂定为:0x001
@1、存储的内容有:
0:12,
1: 23,
length:2
.....
6、定义变量x
基于let声明,存储到VO(G)中
7、x和0x001关脸 x --> 0x001
8.VO(G)中存储的变量:
@1、x -------> 0x001
9、function xxx 也是定义一个变量,基于function/let声明的而变量存在GO中
@1、函数也是一个对象,所以开一个堆内存,16进制地址为:0x002
@2、存储的内容:

10、此时GO中存储的属性:
setTimeout,
setInterval,
requestAnimationFrame,
fn:0x002
..........
11、函数执行并传值:fn(x) ----> fn(0x001)
@1、产生全新的私有执行上下文EC(FUN),然后进栈执行[私有上下文中有个私有变量对象AO(FUN),用来存储私有上下文中声明的变量]
@2、代码正式执行前:

@3、代码执行

 y[0] = 100  
 y = [100]
 y[1] = 200
 console.log(y)

@4、fn执行完后,出栈释放

12、函数执行完,执行全局代码:console.log(x)
刚才已经提到 x指向0x001
0x001中的值在fn执行的时候已给修改成:[100,23]

全局代码在浏览器关掉的时候才会释放

以上就是整个代码的运行机制

总结:

1、创建函数的过程:

@1、开辟堆内存[16进制地址]
@2、存储的内容

@3、把16进制空间地址赋值给变量(函数名)即可

2、普通函数执行要做的事情:

@1、产生全新的私有执行上下文EC(?),然后进栈执行
私有上下文中有私有变量对象AO(G),用来存放私有变量
@2、代码执行前还要做的事情:

3、作用域链

<自己私有上下文,作用域(上级上下文)>
@1、在私有上下文中遇到个变量,首先看是否为私有变量(看AO中是否存在),如果是私有变量,则接下来操作的都是私有变量(和外界都没有关系)
@2、如果不是自己私有的,则去上级上下文中查找,如果是上级的,则操作的都是上级的
@3、如果也不是上级的,则继续找上级的上级的上下文....直到找到EC(G)为止
@4 如果EC(G)中也没有,则:

function fn() {
/* fn执行,形成私有上下文EC(FN)
*      AO(FN):
*      作用域链:<EC(FN),EC(G)>
*      形参赋值:--
*      变量提升:--
*      代码执行
*/
  console.log(n)  //  既不是形参,也没有在这个上下文中声明过,所以AO(FN)中没有,沿着作用域链往上找,全局GO也没有,所以会报错:n is not defined
}
fn()

如果是:

function fn() {
  n = 100   // 相当于给GO中设置一个属性n,值是100 --> window.n = 100
}
fn()
console.log(n, window.n) // 100  100
上一篇 下一篇

猜你喜欢

热点阅读