关于javascript:用一个例子理解JS函数的底层处理机制

40次阅读

共计 1929 个字符,预计需要花费 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 x = [12, 23];运行如下

  1. 开拓堆内存,创立数组值,假如堆内存的地址为 0x000000
  2. 申明变量x
  3. 赋值,行将 x 指向堆内存的地址 0x000000

接着

function fn(y) {y[0] = 100;
    y = [100];
    y[1] = 200;
    console.log(y);
}

运行如下

下面这段代码是创立一个函数的过程。和创立一个变量相似:

  • 都是申明一个变量存储值
  • 步骤一样:第一步也是先创立一个堆内存,外面存的是函数,这个堆内存有一个地址,而后把地址赋值给变量
  • 申明:形式相似函数名也算变量,当咱们申明函数 function fn(y){...} 时,相当于咱们申明了一个变量,只不过值是函数。相似于 var fn = function (y){...} 的函数表达式。最终把一个函数作为值赋值给一个变量或者其余

所以创立一个函数,具体的执行程序如下

  1. 首先开拓一个堆内存,存储函数的值(假如地址为 0x000001)

    • 对象的值在堆内存当中,存储的是它的键值对
    • 函数的值在堆内存当中,存储的是它的代码,而且是以字符串的模式存储的
    • 创立函数的时候,就申明了它的 作用域(scope),scope 值是 以后创立函数的时候所处的上下文,即在哪个上下文中创立的,作用域就是谁
![](/img/bVcHeaq)
  1. 接着申明变量fn,并且指向堆内存地址(假如为 0x000001)

函数执行的步骤

fn(x);运行如下(函数执行的步骤)

  1. 函数执行时,永远传的是值,fn(x)传的是 x 的值,即 x 指向的 0x000000 堆内存地址
  2. fn(0x000000)造成一个全新的 公有上下文 EC(fn)
  3. 在函数造成的新的上下文中,生成一个私有化变量对象 AO,用来存储以后上下文中申明的变量(Active Object 流动对象,简称 AO,变量对象的一种,相似全局上下文中的全局变量)
  4. 外部代码执行之前产生的事

    • 初始化作用域链 scope-chain <EC(fn1),EC(G)>,链的中间是 < 以后本人的公有上下文,函数的作用域(创立函数的时候所在的上下文)>,链的右侧也叫以后上下文的 ’ 下级上下文 ’
    • 初始化 this
    • 初始化 argument
    • 在以后上下文中,申明一个形参变量,并且把传递的实参值赋值给它
    • 变量晋升
![](/img/bVcHeat)
  1. 进栈执行代码
  2. 出栈开释

函数进栈执行代码的具体步骤

接着说说下面第 5 步的具体步骤

把之前创立的函数,在堆内存中存储的代码字符串拿进去转换为代码一行一行的执行执行。

公有上下文中代码执行中如果遇到一个变量,首先看是否为本人的 ’ 公有变量 ’,如果是 ’ 公有 ’ 的,则操作本人的,和外界没有必然的关系,如果不是本人公有的,则基于 作用域链 ,向其 下级上下文 中查找,看是否为下级上下文中公有的,如果也不是,持续向上查找 …… 始终找到 EC(G)全局上下文 为止,咱们把这种查找过程称之为 作用域链查找机制
所以

y[0] = 100
y = [100]
y[1] = 200

是这样的执行的:

  1. y[0] = 100,y当初存储的内存地址为 0x000000,所以批改这个地址下的值:

  2. y = [100],呈现了新的对象值,所以要开拓新的堆内存 0x000002,创立值,赋值

  3. y[1] = 200,将 0x000002 地址对应的对象的值进行批改

  4. console.log(y);这个 y 就是 0x000002 对应的值 [100,200] 操作的是公有变量y

fn函数至此执行结束。

接着执行里面的console.log(x);,此时的 x 为全局变量对象中的 x,对应的地址为 0x000000,所以间接进行输入[100,23]

如果 fn 执行完之后,继续执行其余函数,同样会经验这样的流程。造成新的上下文,进栈执行 … 如果函数十分多,会始终进栈,占内存会越来越大。所以为了优化,浏览器会默认做出很多回收机制

后果与总体流程

后果

总体流程图

其余阐明点

js 上下文分类

js 上下文(哪一个区域下执行)分类

  • 全局上下文 EC(G)
  • 函数执行造成的公有上下文
  • 块级公有上下文

什么是公有变量

公有变量是公有上下文申明的变量,蕴含

  1. 形参
  2. 代码执行的时候申明的变量var / let / const / function

留神与全局变量区别,没有间接关系,然而可能会存在一些间接关系,比方上面这段代码下全局变量 x 的值是 0x000000,通过函数,将 0x000000 传给了公有变量 y,y 也是 0x000000

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

正文完
 0