JavaScript 是一种不可思议的语言,我们每天都在使用它,却并不了解其背后发生了什么。让我们深入探讨 JavaScript 的工作原理,揭开其面纱。
基础:单线程执行
在核心层面,JavaScript 是一种单线程
、同步
语言,这意味着它一次处理一个任务,在一个线程中执行。
尽管 JavaScript 是单线程
的,但它具有异步能力,使其看起来像是多线程
。
JavaScript 运行时解剖:
每个 JavaScript 运行时都包含三个关键组件,它们协同工作:
1- 调用栈:
- 一种数据结构,用于跟踪正在执行的函数。它遵循后进先出(LIFO)的原则------最后添加的函数先被移除。
- 栈底是
全局执行上下文
,即全局代码的环境,随着函数被调用,它们的执行上下文被堆叠在顶部。
2- 内存堆:
- 在程序执行期间,用于存储对象、数组和其他复杂数据结构。
- JavaScript 使用垃圾回收来释放对象所占用的内存。
3- 执行上下文:
- 执行上下文是一种特殊环境,用于处理 JavaScript 代码的执行。
- JavaScript 有一个
全局执行上下文
,以及每个被调用函数的函数执行上下文
。
执行上下文的阶段:
1- 内存创建阶段:
- 创建全局对象(在浏览器中是
window
,在 Node.js 中是global
)。 - 将
this
关键字绑定到全局对象。 - 创建变量并声明:
-
- 对于
var
声明:分配内存并初始化为undefined
(变量提升) - 对于
let
和const
声明:分配内存但保持在临时死区
(未初始化)
- 对于
2- 执行阶段:
- 逐行执行代码。
- 为变量分配实际值。
- 为函数调用创建新的执行上下文。
异步 JavaScript:事件循环和队列
JavaScript 的异步性通过以下机制实现:
任务队列(宏任务队列)
- 一个先进先出(FIFO)的队列,用于存放已准备好执行的回调。
微任务队列
- 一个优先级更高的队列,用于
promise
和其需要在下一个任务之前处理的微任务。
事件循环
- 事件循环是 JavaScript 中异步编程的基础:
- 它持续检查调用栈是否为空。
- 如果调用栈为空,它会先查看微任务队列。
- 处理完微任务后,它会检查任务队列。
- 它会将队列中的第一个回调取出并推入调用栈。
结论
理解 JavaScript 的内部工作原理有助于你编写更高效的代码。从其单线程
特性到事件循环和执行上下文,这些基本概念构成了 JavaScript 行为的骨干。
掌握这些概念后,你将更深入地了解 JavaScript 代码的实际执行过程。
快乐编码 😊