self 是 web worker 和 service worker 中唯一可用的全局对象,window 完全不可用;web worker 中 self 是 workerglobalscope 实例,service worker 中为 serviceworkerglobalscope,二者均需通过 self 访问 api 并避免引用 window。

在 Web Worker 和 Service Worker 中,self 是唯一可用的全局对象,window 完全不可用——这不是兼容性问题,而是规范强制限制。识别关键在于运行环境和作用域边界,而非“兼容性处理”。
Web Worker 中 self 的定位与 window 的缺失
self 在专用或共享 Worker 中是 WorkerGlobalScope 实例,等价于顶层 this,提供 postMessage、importScripts、close 等接口。window 在任何 Worker 内部都未定义,访问会直接报 ReferenceError。
- 可通过
typeof window === 'undefined'明确判断当前不在主线程 - 推荐用
self.constructor.name === 'DedicatedWorkerGlobalScope'确认环境 - 误写
window.postMessage必须改为self.postMessage或直接postMessage(顶层自动绑定)
Service Worker 中 self 的角色与 window 的彻底隔离
Service Worker 运行在 ServiceWorkerGlobalScope,self 是其全局对象,承载生命周期事件(install、fetch、message)和缓存 API(caches)。window 不仅不可用,连其子属性(如 window.location)也完全不存在,试图访问会抛出引用错误。
- 不能依赖
location.href,应改用self.location.href(只读) -
navigator可读部分属性(如navigator.userAgent),但不是window.navigator的副本,而是self.navigator - 所有通信必须通过
self.clients.matchAll()获取页面 client,再调用client.postMessage()
跨环境统一获取全局对象的安全写法
若需编写可同时运行于主线程、Worker、Service Worker 的通用脚本(如工具函数库),应避免硬编码 window 或 self,而用标准方式探测:
const globalObj = typeof globalThis !== 'undefined' ? globalThis : typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : undefined;- 注意:Service Worker 和 Web Worker 中
globalThis就是self,主线程中才是window - 不建议 fallback 到
window,因为 Worker 环境下该变量根本不存在,会导致运行时中断
常见误判场景与验证建议
开发者常把“没报错”当作“可用”,但某些行为具有隐蔽性:
-
console.log(window)在 Worker 中报错,但console.log(typeof window)返回"undefined"—— 应优先用后者做判断 - 在 Service Worker 中调用
fetch()是合法的,但它属于self上的方法,不是window.fetch的代理 - 调试时可在 Worker 脚本开头加
console.info('Running in:', self.constructor.name);快速确认上下文











