JavaScript - 函数 - 函数的底层运行机制


首先做一道练习题

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

答案及解析:在这里插入图片描述

函数执行

函数执行的过程

  1. 创建一个全新的私有上下文 [进栈], 函数中的代码都是在这个私有上下文中执行的。
    • JS中的栈结构:一个栈中有多个上下文,哪个上下文中的代码需要执行,则挪至顶端去执行。
    • 代码执行时形成一个全新的EC(私有上下文)供私有的代码执行。
    • 私有变量对象AO,它是VO的分支,在私有上下文中声明的变量都存储在这里。
  2. 进栈
    • 把全局上下文放到栈底(压缩栈)
    • 新进来的上下文放到栈的顶部
    • 进栈后的操作
      • 初始化作用域链(scopeChain):<自己所在的上下文,函数的作用域>
      • 初始化THIS指向:eg:window (箭头函数没有这一步)
      • 初始化实参集合:arguments(箭头函数没有这一步)
      • 形参赋值:
      • 变量提升:
      • 代码执行:自上而下依句执行,变量提升时处理过的,代码执行时不再重复处理,直接跳过,计算机不做重复的事情
  3. 出栈:
    • 上下文中的代码执行完毕,出栈(可能释放)。
    • 一般情况下,为了优化内存空间,函数执行完毕,所形成的上下文,就会被释放出栈。

形参 & 实参

  • 形参是变量,私有变量,存放到自己上下文中的私有变量对象中。
  • 实参是具体的值。
  • 函数定义设置的是形参,执行传递的是实参。

函数的作用域

  • [[scope]]
    • 函数的作用域主要看函数在哪儿创建的,
    • 与函数在哪儿执行和函数的执行主体都无关。
  • 创建函数的时候,就定义了函数作用域>当前函数创建所在的上下文=>[[scope]]:作用域。
  • 函数执行的目的是想让之前存储在堆中的代码字符串执行 -> 代码执行就要有自己的执行环境。

作用域链的储存规则

  • [[scopeChain]]: <EC(fn),EC(G)>
    • 即: <自己所在的上下文,自己函数的作用域(上级上下文)>,
    • 函数在哪儿创建的,上级上下文就是谁。
    • 从函数创建开始,作用域就已经指定好了。
    • 当前函数在作用域(N)下创建的
      • 那么函数执行形成的作用域(M)的上级作用域就是N,
      • 和函数在哪儿执行的没有任何关系。
      • 只和函数在哪儿创建的有关系。

作用域链查找机制

作用域链是一种机制:“变量查找机制”[scope-shain]。

  • 在当前上下文执行代码的时候,如果遇到一个变量:
  • 首先看是否为自己的私有变量(在私有变量对象中的是私有变量),
    • 如果是,则操作的都是自己的变量,
    • 如果不是私有的变量,则按照作用域链找上级上下文(也就是函数作用域)中是否有这个变量;
  • 如果还不是,一直找到全局上下文EC(G) /GO 为止。
  • 在查找过程中,找到谁的就操作谁的,
  • 找不到则报错提示:xxx is not defined

面试题练习

let x = 1;
function A(y){
	let x = 2;
	function B(z){
		console.log(x + y + z);
	};
	return B;
}
let C = A(2);
C(3);

图形解析:
在这里插入图片描述

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值