运行流程

  • 编译
    • JavaScript 代码被解析成 AST,生成字节码。
  • 执行上下文
    • 创建全局或函数执行上下文,设置变量、词法环境和 this
  • 调用栈
    • 按照代码顺序管理函数的执行上下文。
  • 事件循环
    • 执行同步任务,处理异步任务队列。
  • 垃圾回收
    • 自动释放不再使用的内存。

JavaScript 代码的编译与解释

JavaScript 是一种解释执行的语言,但现代 JavaScript 引擎(如 V8)采用了即时编译(JIT)技术,将代码分为解析执行两个阶段。

解析阶段

  • 源代码被解析为抽象语法树(AST)。
  • 编译器对代码进行初步优化并生成字节码。

执行阶段

  • 字节码被逐行解释执行。
  • 如果某段代码执行频繁,优化编译器(如 V8 的 TurboFan)会将其编译为机器码以提高执行效率。

执行上下文的创建

每段 JavaScript 代码的执行都发生在某个执行上下文中。

  • 全局执行上下文
    • 在代码执行前创建,用于管理全局作用域。
  • 函数执行上下文
    • 每当函数被调用时,都会为该函数创建一个新的执行上下文。
  • 模块执行上下文(ES6+):
    • 模块化代码会有自己的作用域和上下文。

执行上下文的组成

  • 变量环境:存储变量和函数声明。
  • 词法环境:用于存储变量的作用域和嵌套关系。
  • this 绑定:表示当前上下文中的 this 值。

调用栈的管理

调用栈(Call Stack)是一个栈结构,用于管理执行上下文的顺序。

调用栈的工作原理

  • 每当函数被调用时,创建新的执行上下文并压入栈顶。
  • 函数执行完毕后,从栈顶弹出。

function foo() {
console.log(‘foo’);
}

function bar() {
foo();
}

bar();

调用栈变化

  1. 全局上下文入栈。
  2. bar 的执行上下文入栈。
  3. foo 的执行上下文入栈。
  4. foo 执行完毕,出栈。
  5. bar 执行完毕,出栈。
  6. 全局上下文出栈。

代码的执行顺序

JavaScript 是单线程语言,代码的执行分为两种任务

  • 同步任务:直接执行,进入调用栈。
  • 异步任务:交给任务队列,通过事件循环调度执行。

事件循环的运行机制

事件循环是 JavaScript 处理异步任务的核心机制:

  1. 执行调用栈中的同步代码。
  2. 检查微任务队列(Microtasks),执行所有微任务。
  3. 执行一个宏任务(Macro-task)。
  4. 重复上述过程。

任务类型

  • 宏任务(Macro-task):如 setTimeoutsetInterval、I/O 操作等。
  • 微任务(Micro-task):如 Promise.thenMutationObserver

console.log(‘start’);

setTimeout(() => {
console.log(‘setTimeout’);
}, 0);

Promise.resolve().then(() => {
console.log(‘Promise’);
});

console.log(‘end’);

输出顺序

start
end
Promise
setTimeout

内存分配与垃圾回收

avaScript 自动管理内存,通过垃圾回收器回收不再使用的内存。

  • 堆内存(Heap):用于存储对象。
  • 栈内存(Stack):用于存储基本类型和函数调用。

 

 

作者 admin

百度广告效果展示