我们经常需要处理来自不同来源的代码,无论是第三方的广告、分析脚本、用户自定义插件,还是动态加载的模块,将这些不受信任或半信任的代码集成到我们的应用中时,总会伴随着巨大的风险。
为了解决这些问题,开发者们曾尝试过各种方法,如 iframe 、Web Workers,甚至是危险的 eval 。但它们各有缺点:iframe 过于笨重,通信复杂;Web Workers 是异步的,不适合需要同步执行的场景; eval 则完全没有隔离性。
什么是 ShadowRealm?
** ShadowRealm ** 是一个正在制定的 ECMAScript 标准,它允许开发者创建一个全新的、被隔离的 JavaScript **
全局环境(Global Environment) ** 。
我们可以把它想象成一个轻量级的、纯粹为 JavaScript 准备的 iframe ,但它没有
DOM、没有渲染开销,并且能够以一种可控的方式进行同步通信。
每个 ShadowRealm 实例都拥有自己独立的全局对象( globalThis )和一套完整的内建 JavaScript
对象(如 Object , Array , Promise 等)。在其中执行的代码无法访问主页面的 window 或 document ,从而实现了强大的安全隔离。
核心概念与 API 用法
ShadowRealm 的 API 设计得非常简洁。主要包含以下几个部分:
** 创建 Realm ** :
通过 new ShadowRealm() 构造函数可以轻松创建一个新的 Realm。
// 在主环境中
const realm = new ShadowRealm();
** 执行代码 ** :
使用 evaluate() 方法可以在 Realm 内部执行一段 JavaScript 代码字符串。这段代码会返回一个
Promise,解析后的值是代码的最终执行结果。

** 注意 ** : evaluate 内部的代码无法访问外部作用域的任何变量。
** 导入函数 ** :
evaluate() 很有用,但更强大的功能是与 Realm 内部的函数进行交互。 importValue() 方法允许我们从
Realm 内部导入一个函数,以便在主环境中调用它。
// `greet` 是在上面 evaluate 中定义的函数
const wrappedGreet = await realm.importValue(
// 'greet' 是 Realm 中全局可用的函数名
'greet'
);
// 调用这个“包装后”的函数
const message = await wrappedGreet('World');
console.log(message); // 输出: "Hello from the Realm, World!"
截至目前,ShadowRealm API 处于 ** TC39 流程的 Stage 3 ** ,意味着其设计已经稳定,只待浏览器厂商广泛实现和最终批准。