Mặc định postMessage(value) dùng structured clone: dữ liệu được sao chép sang thread kia. Chi phí tỉ lệ với kích thước, và việc serialize/deserialize chạy đồng bộ trên chính thread gọi — gửi một object 50MB nghĩa là chặn event loop trong lúc clone. Structured clone mạnh hơn JSON (giữ được vòng tham chiếu, Map, Set, Date, typed array) nhưng không mang được function, class instance hay closure.
transferList — chuyển quyền sở hữu, không sao chép.
const buf = new ArrayBuffer(50 * 1024 * 1024)
worker.postMessage({ buf }, [buf]) // zero-copy: ownership moves
// buf.byteLength is now 0 on this sideChỉ nhận ArrayBuffer, MessagePort và vài kiểu transferable khác. Sau khi chuyển, bên gửi không dùng lại được — vùng nhớ đã thuộc thread nhận. Đây là cách đúng để đẩy dữ liệu nhị phân lớn một chiều.
SharedArrayBuffer — hai thread cùng đọc ghi một vùng nhớ. Không sao chép, không chuyển quyền, và không được đưa vào transferList (chỉ cần gửi kèm value là cả hai bên thấy). Đổi lại phải tự đồng bộ bằng Atomics (Atomics.wait, Atomics.notify) — có race condition thật như lập trình đa luồng cổ điển.
Chọn thế nào:
- Payload nhỏ, cấu trúc phức tạp → structured clone bình thường.
- Khối nhị phân lớn, gửi một chiều (ảnh, file) → transferList.
- Trạng thái dùng chung, cập nhật liên tục hai chiều → SharedArrayBuffer + Atomics.
Nguyên tắc chung: thiết kế để truyền ít dữ liệu. Gửi đường dẫn file hay khóa cache thường rẻ hơn nhiều so với gửi nội dung.