JavaScript Engine

Chương 3: JavaScript Engine — Bên Trong Bộ Não Của JavaScript

1. Tổng Quan JavaScript Engine

JavaScript Engine là thành phần cốt lõi trong trình duyệt và các runtime khác (như Node.js) giúp chạy mã JavaScript. Nhiệm vụ của engine bao gồm:

  • Phân tích (parsing) mã nguồn JS

  • Biên dịch và tối ưu hoá mã

  • Quản lý bộ nhớ

  • Thực thi code

Các JavaScript Engine phổ biến:

  • V8 (Google): Chrome, Edge, Node.js

  • SpiderMonkey (Mozilla): Firefox

  • JavaScriptCore (Apple): Safari

  • Hermes (Meta): React Native

2. Stack, Heap và Memory Management

JavaScript chia vùng nhớ thành:

  • Call Stack: lưu trữ context khi hàm được gọi

  • Heap: vùng nhớ cho object, closure, array...

Object được lưu trên Heap vì chúng có kích thước thay đổi linh hoạt. Stack là vùng nhỏ nhanh, có cấu trúc LIFO.

3. Execution Context và Call Stack

Khi JavaScript thực thi:

  1. Tạo Global Execution Context

  2. Khi hàm được gọi, context mới được đẩy vào Call Stack

  3. Khi hàm kết thúc, context được pop ra

Mỗi Execution Context gồm:

  • Variable environment (biến, closure)

  • Scope chain

  • this

4. Event Loop và Concurrency Model

JavaScript là ngôn ngữ single-threaded, nhưng hỗ trợ mô hình asynchronous non-blocking I/O nhờ vào Event Loop:

  1. Call Stack thực thi synchronous code

  2. Asynchronous code (đặt trong callback, promise) được đẩy vào Task Queue / Microtask Queue

  3. Event Loop đẩy task vào stack khi stack rỗng

5. Microtask vs Macrotask

  • Macrotask Queue: setTimeout, setInterval, I/O

  • Microtask Queue: Promise.then, MutationObserver

Luôn xử lý Microtask Queue trước khi chuyển sang Macrotask tiếp theo.

console.log('Start');
setTimeout(() => console.log('Timeout'), 0);
Promise.resolve().then(() => console.log('Promise'));
console.log('End');

Output:

Start
End
Promise
Timeout

6. Just-In-Time Compilation (JIT)

JIT là kỹ thuật biên dịch trung gian:

  • JavaScript được parse -> bytecode

  • Bytecode được thực thi ngay (Interpreter)

  • Code hay dùng được tối ưu hoá và compiles sang machine code (via JIT Compiler)

Hai vòng JIT trong V8:

  • Ignition: interpreter tạo bytecode nhanh

  • TurboFan: optimizer tối ưu hoá mã runtime

7. Hidden Classes & Inline Caching

Hidden Classes:

  • Engine tạo hidden class khi object được khai báo

  • Khi các object cùng "hình dạng", chúng chia sẻ chung hidden class

Inline Caching:

  • Ghi nhớ kiểu truy cập properties để tăng tốc

function access(obj) {
  return obj.count;
}
access({ count: 1 }); // Hot path

Việc thay đổi kiểu object runtime khiến optimizer mất hiệu quả (de-optimization).

8. Garbage Collection (GC)

JavaScript Engine sử dụng GC để tự động thu hồi bộ nhớ:

  • Thuật toán Mark-and-Sweep: đánh dấu object có thể truy cập được -> xóa những cái còn lại

let obj = { name: 'JS' };
obj = null; // Object bị thu gom

Cần tránh retain reference trong closure vô ý hoứng!

9. Tổng Quan Về Engine Phổ Biến

Engine
Tổ Chức
Đặc Điểm

V8

Chrome, Node.js

JIT, Inline Cache

SpiderMonkey

Firefox

Debugging Tools

JavaScriptCore

Safari

Bytecode + JIT

Hermes

React Native

Tối ưu mobile

10. Kinh Nghiệm Tối Ưu Dựa Vào Engine

  • Tránh thay đổi structure object runtime (deopt)

  • Không trồn nhiều kiểu trong array

  • Dùng closure có kiểm soát

  • Biết rõ chi phí async / sync / memory

Kết Luận

Hiểu rõ cách Engine hoạt động là nền tảng quan trọng cho bất kỳ senior developer nào. Nó giúp bạn tối ưu hoá, debug và lý giải nhiều hành vi kỳ lạ trong JS.


Last updated