# 函数执行

创建函数的机制

1、开辟一个堆内存(16进制的内存地址:AAAFFF111)
2、声明当前函数的作用域(在哪个上下文中创建的,它的作用域就是谁),并记录形参
3、把函数体中的代码当做“字符串”存储在堆内存中(创建一个函数,存储的是一堆字符串,所以函数只要不执行,函数其实没意义)
4、把函数堆的地址类似于对象一样,放置在栈中供变量(函数名)调用

函数执行的机制

1、会形成一个全新的私有上下文 EC(xx)(目的是供函数体中的代码执行),然后进栈执行

2、在私有上下文中有一个存放私有变量的变量对象 AO(xx)

3、在代码执行之前要做如下:

初始化它的作用域链 <自己的上下文,函数的作用域>
初始化THIS
初始化arguments实参集合(箭头函数没有arguments)
形参赋值(形参变量是函数的私有变量,需要存储在AO中的)
变量提升(在私有上下文忠声明的变量都是私有变量)
...

4、代码执行(把之前在函数堆中存储的字符串,拿过来在上下文当中依次执行)

作用域链查找机制:在代码执行中,遇到一个变量,首先看一下是否为自己的私有变量
如果是自己的私有变量,接下来所有操作都是私有的(和外接没有直接的联系);
如果不是自己私有的,则按照scope-chain,向上级上下文中查找(如果是上级私有的,接下来的操作都是操作上级上下文中的变量)...一直找,直到找到EC(G)为止

5、根据实际的情况确定当前上下文是否出栈释放

为了保证栈内存的大小(内存优化),一般情况下,如果当前函数执行产生的上下文,在进栈且代码执行完成后,会把函数产生上下文移除栈(上下文释放到了:之前在上下文存储的私有的变量等信息也就跟着释放了)

全局上下文是在打开页面生成的,也需要在关闭页面的时候释放掉(只有页面关闭才会被释放掉)

特殊情况:只要当前上下文中的某些内容,被上下文以外的东西占用,那么当前上下文是不能被释放的(上下文存储的变量等信息也保留下来了) => 这种情况也就是闭包

[例题]

var x = [12, 23]; 
function fn(y) {

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

}
fn(x); 
console. log(x); 

[例题的解题步骤兼函数创建执行的过程]

var fn = xxx; 
function fn(){}; 

两个fn都是全局变量,而且是同一个变量,只是赋值不一样
(function fn(){}相当于声明一个变量,变量存储的值时函数而已)