4.函数底层处理机制(创建+执行)

91 阅读2分钟

函数创建「和创建变量区别不是很大 -> 函数名其实就是变量」

  1. 单独开辟一个堆内存「16进制地址」,函数堆内存中存储的是函数体重的“代码字符串”
  2. 创建函数的时候,就声明了它的作用域[scope],也就是所在的上下文环境
  3. 把16进制的地址存放到栈中,供变量(函数名等)关联引用

函数执行过程

  1. 形成以全新的、私有上下文EC(...)
  2. 当前私有上下文中,有一个存放本上下文内声明的变量的地方AO(...)私有变量对象 -> 这里的变量都是当前上下文的私有变量「当前上下文中声明的变量、形参变量」
  3. 进栈执行
  4. 代码执行之前还要处理很多事情
    1. 初始化作用域链[scope-chain] <当前自己的上下文,上级上下文(创建函数时候形成的作用域)>
      -> 当前函数的上级上下文是创建函数所在的上下文(作用域)
      后期函数内代码执行,遇到一个变量,我们首先看是否为自己上下文中的私有变量(看AO中有没有),如果是私有的变量,则当前变量的操作和外界环境中的变量互不干扰(没有直接关系,如果引用类型也是间接关系);如果不是自己的私有变量,则按照作用域链,查找是否为其上级上下文中的私有变量。。。直到找到EC(G)全局上下文为止,称为“作用域链机制”
    2. 初始化this...
    3. 初始话arguments...
    4. 形参赋值:形参都是私有变量(放到AO中的) 如果不传递实参值,默认值是undefined ...
    5. 变量提升...
  5. 代码自上而下执行...
  6. 一般情况下,函数执行所形成的的上下文,进栈执行完后,会默认出栈释放掉「私有上下文中存储的私有变量和一些值都会释放掉」 -> 目的:为了优化内存空间,减少栈内存的消耗,提高页面或者计算机的处理速度...

1.

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

2.

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