前端基石:函数的底层执行机制

简介: 本文主要讲函数的底层执行机制

网络异常,图片无法展示
|


一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情


函数的创建


一个函数的创建会在 Heap 堆内存中开辟一块空间来存储函数。对象在创建会在堆内存中存储对象的键值对,而函数在堆内存中会存储三部分东西:


  • 作用域:[[scope]]
  • 函数字符串
  • 键值对


例如:

let a = [1,2];
function fn(b) {
  b[0] = 3;
  b = [4];
  b[1] = 5;
  console.log(b);
}
fn(a);
console.log(a);

网络异常,图片无法展示
|


对象虽然包含函数,但是函数的创建和其他对象的创建在存储内容上存在一些差别:


  1. 在 Heap 堆内存中分配一块空间(16进制地址)。
  2. 存储相关的内容:
  • 函数对象存储三部分
  1. 创建函数的时候声明作用域[[scope]],函数在那个上下文中创建,其作用域就是谁。
  2. 把函数体中的代码当做字符串存储起来。
  3. 把函数当做普通对象存储一些键值对
  • 其余对象存储键值对
  1. 把创建的内存地址赋值给对应的变量或者函数,易变后续的操作。


函数的执行


1. 创建私有上下文


函数一旦执行,就会创建一个全新的私有上下文「进栈」,函数每一次执行 都是重新形成一个全新的私有上下文,和之前执行产生的上下文没有必然的联系,函数中的代码都是在私有上下文中进行执行的。函数进栈执行会创建一个私有变量对象 AO(Active Object),这里区分开 VO。AO 是 VO 的一个分支。在私用上下文中创建的变量都会存储在 AO 中,例如形参、变量提升和函数中定义的变量。


2. 完成初始化操作


完函数进栈后,正式开始执行之前,会进行一些初始化的操作:

  • 初始化作用域链<<自己的私有上下文,作用域>>。
  • 初始化 this (箭头函数没有这一步)。
  • 初始化 arguments (箭头函数没有这一步)。
  • 形参赋值。
  • 变量提升。


3. 代码执行


将堆内存中存在的代码字符串从上往下的顺序进行执行。


4. 出栈释放或者保留


正常情况下,代码执行完成之后,私有上下文出栈被回收。但是遇到特殊情况,如果当前私有上下文执行完成之后中的某个东西被执行上下文以外的东西占用,则当前私有上下文就不会出栈释放,也就是形成了不被销毁的上下文,闭包。除了这上面两种情况还有一种情况是,上下文没有被占用,但是要紧接着被用一次,这样没有用完之前是不能释放的,用完在释放,这样就形成了一个临时不被释放 )。

函数每一次执行都是重新形成一个全新的私有上下文,意思就是如果一个函数被执行100次,也会对上面的步骤走100次,并且形成100个执行上下文。正常情况下,函数执行完就会出栈被释放,但是如果不能被释放(闭包),就会一直被保存在内存中,当达到栈内存的极限时就会出现爆栈。

还是用这段代码为例:


let a = [1,2];
function fn(b) {
  b[0] = 3;
  b = [4];
  b[1] = 5;
  console.log(b);
}
fn(a);
console.log(a);

网络异常,图片无法展示
|


参考


目录
相关文章
|
4月前
|
前端开发 JavaScript 开发者
揭秘JavaScript魔法三剑客:call、apply、bind,解锁函数新世界,你的前端之路因它们而精彩!
【8月更文挑战第23天】在 JavaScript 的世界里,`call`、`apply` 和 `bind` 这三个方法常常让新手感到困惑。它们都能改变函数执行时的上下文(即 `this` 的指向),但各有特点:`call` 接受一系列参数并直接调用函数;`apply` 则接收一个参数数组,在处理不确定数量的参数时特别有用;而 `bind` 不会立即执行函数,而是创建一个新版本的函数,其 `this` 上下文已被永久绑定。理解这三个方法能帮助开发者更好地运用函数式编程技巧,提升代码灵活性和可维护性。
43 0
|
2月前
|
存储 监控 前端开发
掌握微前端架构:构建未来前端应用的基石
【10月更文挑战第12天】随着前端技术的发展,传统的单体应用架构已无法满足现代应用的需求。微前端架构通过将大型应用拆分为独立的小模块,提供了更高的灵活性、可维护性和快速迭代能力。本文介绍了微前端架构的概念、核心优势及实施步骤,并探讨了其在复杂应用中的应用及实战技巧。
|
2月前
|
前端开发 JavaScript
前端:实现一个 sleep 函数
在前端开发中,实现一个 `sleep` 函数可以用来暂停代码执行,模拟延迟效果,常用于测试或控制异步操作的节奏。该函数通常基于 `Promise` 和 `setTimeout` 实现,简单易用。
|
3月前
|
存储 前端开发 JavaScript
前端基础(十二)_函数高级、全局变量和局部变量、 预解析(变量提升)、函数返回值
本文介绍了JavaScript中作用域的概念,包括全局变量和局部变量的区别,预解析机制(变量提升),以及函数返回值的使用和类型。通过具体示例讲解了变量的作用域、函数的返回值、以及如何通过return关键字从函数中返回数据。
25 1
前端基础(十二)_函数高级、全局变量和局部变量、 预解析(变量提升)、函数返回值
|
2月前
|
JSON 前端开发 JavaScript
构建现代前端应用的基石
【10月更文挑战第13天】构建现代前端应用的基石
|
3月前
|
存储 前端开发 JavaScript
前端基础(十一)_函数声明及调用、函数的形参与实参、arguments参数、函数的参数类型、函数中的问题
本文介绍了JavaScript中函数的声明及调用、形参与实参的概念、arguments对象的使用、函数参数的类型以及函数中this的作用。通过示例代码详细解释了函数如何接收参数、如何处理参数个数不匹配的情况,以及函数在不同上下文中this的指向。
29 1
|
4月前
|
JSON 前端开发 API
构建前端防腐策略问题之更新getMemoryUsagePercent函数以适应新的API返回格式的问题如何解决
构建前端防腐策略问题之更新getMemoryUsagePercent函数以适应新的API返回格式的问题如何解决
构建前端防腐策略问题之更新getMemoryUsagePercent函数以适应新的API返回格式的问题如何解决
|
3月前
|
JavaScript 前端开发
前端JS函数
【9月更文挑战第4天】前端JS函数
29 6
|
5月前
|
开发框架 前端开发 JavaScript
循序渐进VUE+Element 前端应用开发(22)--- 简化main.js处理代码,抽取过滤器、全局界面函数、组件注册等处理逻辑到不同的文件中
循序渐进VUE+Element 前端应用开发(22)--- 简化main.js处理代码,抽取过滤器、全局界面函数、组件注册等处理逻辑到不同的文件中
|
5月前
|
开发框架 JSON 前端开发
循序渐进VUE+Element 前端应用开发(7)--- 介绍一些常规的JS处理函数
循序渐进VUE+Element 前端应用开发(7)--- 介绍一些常规的JS处理函数