
创建一个函数
1.开辟一个堆内存(16进制的内存地址:AAAFFF000)
2.声明当前函数的作用域(在哪个上下文中创建的,它的作用域就是谁)
3.把函数体中的代码当做“字符串”存储在堆内存中(创建一个函数,存储的是一堆字符串,所以函数只要不执行,函数其实没啥意义)
4.把函数堆的地址类似于对象一样,放置在栈中供变量调用(函数名)
执行函数
1.会形成一个全新的私有上下文 EC(xx)(目的是供函数体中的代码执行),然后进栈执行
2.在私有上下文中有一个存放私有变量的变量对象 AO(xx)
3.在代码执行之前要做的事情很多:
* 初始化它的作用域链 <自己上的上下文,函数的作用域>
* 初始化THIS (箭头函数没有THIS)
* 初始化ARGUMENTS实参集合(箭头函数没有ARGUMENTS)
* 形参赋值(形参变量是函数的私有变量,需要存储在AO中的)
* 变量提升(在私有上下文中声明的变量都是私有变量)
* ......
4.代码执行(把之前在函数堆中存储的字符串,拿过来在上下文中依次执行)
* 作用域链查找机制:在代码执行中,遇到一个变量,我们首先看一下是否为自己的私有变量,如果是自己的私有变量,接下来所有操作都是操作私有的(和外界没有直接的联系);如果不是自己私有的,则按照scope-chain,向上级上下文中查找(如果是上级私有的,接下来的操作都是操作上级上下文中的变量)....一直找,直到找到EC(G)为止
5.根据实际的情况确定当前上下文是否出栈释放
* 为了保证栈内存的大小(内存优化),一般情况下,如果当前函数执行产生的上下文,在进栈且代码执行完成后,会把次上下文移除栈(上下文释放到了:之前在上下文中存储的私有的变量等信息也就有跟着释放了) =>全局上下文是在打开页面生成的,也需要在关闭页面的时候释放掉(只有页面关闭才会被释放掉)
* 特殊情况:只要当前上下文中的某些内容,被上下文以外的东西占用,那么当前上下文是不能被释放的(上下文中存储的变量等信息也保留下来了) =>这种情况就是大家认为的闭包