Web Workers 提供后台线程运行脚本的机制,主线程与 Worker 线程隔离,仅通过 postMessage 通信;必须加载外部 js 文件,不可内联;Worker 中无法操作 dom 或访问 window、document 等对象。

javaScript 本身是单线程的,Web Workers 不是“让 JS 变成多线程”,而是提供一种**在后台线程运行脚本**的机制,主线程和 Worker 线程彼此隔离、通过消息通信 —— 这是关键前提,否则容易误以为能直接共享变量或 DOM。
Worker 创建必须用外部 JS 文件(不能内联)
浏览器强制要求 Worker 构造函数接收一个 外部 javascript 文件路径,不支持字符串或内联函数。这是安全限制,也是常见报错源头:
const worker = new Worker('worker.js'); // ✅ 正确
const worker = new Worker('data:text/javascript,console.log("hi")'); // ❌ 大部分浏览器拒绝
const worker = new Worker(function() { console.log('no'); }); // ❌ 语法错误
如果你用构建工具(如 vite、webpack),可用 new Worker(new URL('./worker.js', import.meta.url), { type: 'module' }) 来支持模块语法,但本质仍是加载一个独立文件。
postMessage 是唯一通信方式,且只能传可序列化数据
主线程和 Worker 之间无法访问对方作用域,所有交互必须靠 postMessage + onmessage。注意:
立即学习“Java免费学习笔记(深入)”;
-
postMessage第一个参数会被结构化克隆(structured clone),function、undefined、symbol、promise、DOM 节点都无法传递 - 如果要传大数组或二进制数据,用
Transferable(如ArrayBuffer)避免拷贝:worker.postMessage(arrayBuffer, [arrayBuffer]); - Worker 内部用
self.postMessage发送,监听用self.onmessage,不是window对象
Worker 中不能操作 DOM、document 或 window
这是最常被忽略的边界。Worker 运行在完全独立的上下文,没有 document、window、localStorage、alert,甚至没有 setTimeout 的完整语义(只有 self.setTimeout,但不可靠)。典型误用:
// 在 worker.js 中 ❌ document.body.innerhtml = 'loading...'; // TypeError: document is not defined console.log(window.location); // ReferenceError: window is not defined
Worker 适合做的事包括:json.parse 大文本、加密/解密、图像像素计算、复杂数学运算、离线缓存预处理 —— 所有不依赖 ui 的纯计算任务。
真正难的不是创建 Worker,而是设计好主线程与 Worker 的消息协议、错误回传机制、以及如何优雅终止(worker.terminate() 或 self.close())。很多性能问题其实源于频繁创建/销毁 Worker,而不是计算本身。