ECMA262标准中的Realm是什么?为什么ECMAScript代码需要关联Realm?
什么是ECMA262中的Realm?
Realm是ECMAScript规范定义的独立代码运行上下文容器,你可以把它理解为JS引擎层面的基础沙箱单元,所有JS代码的执行都必须依附在对应的Realm上,每个Realm都持有一套完全独立、和其他Realm互不共享的运行基础资源,核心属性的作用如下:
- [[GlobalObject]]:即全局对象,对应浏览器里的
window、Node.js里的global等实体,所有全局作用域下声明的变量、函数都会挂载到这个对象上。 - [[GlobalEnv]]:全局词法环境,负责处理全局作用域的变量查询、赋值、作用域链查找等逻辑,和[[GlobalObject]]直接绑定。
- [[Intrinsics]]:内置对象集合,包含我们常用的
Object、Array、Promise、Function等所有原生构造器以及它们的原型方法,每个Realm的内置对象都是独立副本,不会互相影响。 - [[TemplateMap]]:模板字符串缓存表,用来存储模板字面量的解析结果,保证同一段模板字面量在同一个Realm内多次求值时返回的是同一个模板对象。
- [[HostDefined]]:宿主扩展字段,是规范给浏览器、Node.js等JS运行时预留的自定义配置位,用来存储宿主特定的运行参数。
为什么所有JS代码都必须关联Realm?
你查到的规范表述其实已经点出了核心逻辑:
所有ECMAScript代码在被求值之前,必须与一个realm相关联
这句描述的本质是:JS代码运行依赖的所有基础资源都存储在Realm中,没有对应的Realm,代码连[]、{}、基础类型判断这类最基础的操作都无法完成。Realm存在的必要性可以从三个实际场景理解:
- 运行环境隔离需求
最常见的例子是浏览器中的iframe,每个iframe都对应一个独立的Realm,所以你从iframe中拿到的数组实例,在父页面执行arr instanceof Array会返回false——因为父页面的Array构造器和iframe的Array构造器属于不同Realm的[[Intrinsics]],是完全独立的两个函数。如果没有Realm做隔离,不同iframe的全局对象、内置对象会互相污染,跨域安全、页面稳定性都无法保障。
除此之外Node.js的vm模块、浏览器的ShadowRealmAPI都是基于Realm实现的,用来运行不受信任的第三方代码,避免污染主程序的运行环境。 - 规范层统一抽象需求
JS的宿主环境非常多,浏览器、服务端、嵌入式设备、小程序运行时都可以运行JS,Realm是ECMA262给所有宿主定义的统一抽象层,不管宿主怎么扩展自身能力、怎么实现沙箱逻辑,只要符合Realm的结构要求,就能保证JS基础语法的执行行为和规范一致,不会出现不同宿主下基础逻辑表现不一致的问题。 - 执行上下文的依赖需求
每个Execution Context(执行上下文)都必须绑定对应的Realm,执行上下文负责处理代码运行时的作用域链查找、this绑定、变量赋值等逻辑,这些逻辑都需要从关联的Realm中获取全局环境、内置对象等资源才能正常执行。比如你在任意函数中调用Object.prototype.toString.call([]),JS引擎就是从当前执行上下文关联的Realm的[[Intrinsics]]中拿到对应的Object原型方法的。
内容的提问来源于stack exchange,提问作者AngryJohn
相关产品推荐
相关产品推荐

