
core-jsweb.self模块深度解析self全局属性 Polyfill 的实现原理与工程实践【免费下载链接】core-jsStandard Library项目地址: https://gitcode.com/GitHub_Trending/co/core-js导读本文以 core-js 仓库中 docs/web/docs/features/web-standards/self.md 文档为主线深入剖析web.self模块如何为现代 JavaScript 引擎补齐 HTML 规范定义的self全局属性。你将掌握self的规范来源与语义、core-js 的完整实现源码与降级策略、多种入口点的正确使用方式以及它在 Web Worker、Deno、Node.js 等环境下的实际工程价值。self一个容易忽略却至关重要的全局属性self是 HTML 规范WHATWG HTML Standard中定义的全局属性在 Window 对象规范中将其定义为指向全局对象本身的访问器属性。它的核心语义非常简单self始终指向当前环境的全局对象。在浏览器环境包括 Window、Worker、SharedWorker 等所有全局作用域中self都是一个长期存在且被广泛使用的标准全局属性。它之所以重要是因为在 Web Worker / Service Worker 环境中window不存在但self依然可用是编写浏览器通用脚本的可靠锚点在 Node.js 的早期版本中既没有window也没有标准化的self这导致同一份代码难以在浏览器与 Node 间无缝复用。而 core-js 的web.self模块源码位于 packages/core-js/modules/web.self.js就是用来消除这种环境差异、补齐self全局属性的标准 polyfill。它属于 core-js 中Web 标准web standards一类与web.atob、web.btoa、web.queue-microtask、web.structured-clone等模块并列共同收录于 packages/core-js/web/index.js 的 Web 标准聚合入口中。规范语义与 Polyfill 的目标行为根据规范self是一个指向全局对象的只读不可赋值覆盖访问器属性。core-js 文档 docs/web/docs/features/web-standards/self.md 给出了其类型签名getter self: GlobalThisValue;即self是一个仅含 getter 的属性读取时返回全局对象本身。文档给出的验证示例直观地说明了这一点self.Array Array; // true因为self就是全局对象所以全局对象上的所有内建属性如Array、Math、Object等都可以通过self.xxx访问到且与直接引用完全相等。源码实现一个条件化、渐进增强的 getterweb.self模块的核心实现位于 packages/core-js/modules/web.self.js其设计思路是仅在必要且安全时才修改全局对象实现了一个典型的检测—降级—定义三步流程。第一步检测当前环境的缺陷模块首先计算一个关键标志位var INCORRECT_VALUE globalThis.self ! globalThis;它通过比较globalThis.self与globalThis是否相等来判断当前引擎中self是否存在或是否正确。若二者不相等说明self缺失或指向错误需要 polyfill。模块获取全局对象的途径是 packages/core-js/internals/global-this.js 中导出的globalThis工具——这个工具按照globalThis→window→self→global→this→Function(return this)的顺序探测全局对象是 core-js 内部所有需要访问全局对象模块的统一基础设施。第二步能力检测决定两条实现路径if (DESCRIPTORS) { // 路径 A通过 accessor descriptor 定义 } else { // 路径 B直接赋值简单属性 }这里的DESCRIPTORS来自 packages/core-js/internals/descriptors.js用于检测引擎是否支持完整的Object.defineProperty即属性描述符能力。在支持描述符的现代引擎中模块会走路径 A——精确定义一个符合规范的访问器属性。路径 A定义符合规范的 accessor在支持属性描述符的引擎中模块首先读取全局对象上现有的self描述符检查它是否足够好var descriptor Object.getOwnPropertyDescriptor(globalThis, self); // 某些引擎虽然有 self但描述符不正确 // 例如 Deno 的历史缺陷https://github.com/denoland/deno/issues/15765 if (INCORRECT_VALUE || !descriptor || !descriptor.get || !descriptor.enumerable) { defineBuiltInAccessor(globalThis, self, { ... }); }源码注释明确提到了 Deno 的 issue #15765某些引擎如当时的 Deno虽然暴露了self但其描述符不符合规范例如缺少 getter 或不可枚举此时 core-js 会主动修复。修复条件为以下任一成立INCORRECT_VALUE为真self值不正确全局对象上没有self描述符描述符没有get方法描述符不可枚举。修复动作通过 packages/core-js/internals/define-built-in-accessor.js 完成该工具会调用makeBuiltIn为 getter/setter 标记内置函数身份最终经由Object.defineProperty定义如下访问器{ get: function self() { return globalThis; }, set: function self(value) { if (this ! globalThis) throw new $TypeError(Illegal invocation); defineProperty(globalThis, self, { value: value, writable: true, configurable: true, enumerable: true }); }, configurable: true, enumerable: true }值得注意的细节是规范的self是纯 getter但 core-js 出于兼容性考虑额外提供了 setter——只有在调用者不是全局对象时如通过someObject.self x才抛出TypeError(Illegal invocation)若直接在全局上赋值self x则允许将其替换为一个普通数据属性。这种宽容的降级设计兼顾了规范语义与旧代码的兼容性。路径 B不支持描述符引擎的简单降级在 IE8 这类不支持完整属性描述符的古老引擎中DESCRIPTORS为假core-js 走最简单的降级路径——直接将self作为全局对象的普通属性赋值为globalThis$({ global: true, simple: true, forced: INCORRECT_VALUE }, { self: globalThis });这里通过 packages/core-js/internals/export.js 提供的$导出函数以forced: INCORRECT_VALUE仅在确实需要时才写入避免多余修改。防御性兜底整个定义逻辑包裹在try/catch中catch (error) { /* empty */ }因为某些环境的全局对象是冻结的如部分沙箱或严格 CSP 环境定义失败时静默跳过绝不抛出异常影响应用启动。单元测试如何验证self的正确性core-js 为web.self提供了全局版本与 pure 版本两套测试分别验证不同交付形态下的行为。全局版本tests/unit-global/web.self.jsQUnit.test(self, assert { assert.same(self, Object(self), is object); assert.same(self.Math, Math, contains globals); if (DESCRIPTORS) { const descriptor Object.getOwnPropertyDescriptor(self, self); assert.true(descriptor.enumerable, enumerable); } });它断言self本身是对象Object(self)与原值相同、self.Math Math全局属性可访问且在支持描述符的引擎中self属性是可枚举的。pure 版本tests/unit-pure/web.self.jsimport self from core-js-pure/stable/self; QUnit.test(self, assert { assert.same(self, Object(self), is object); assert.same(self.Math, Math, contains globals); });pure 版本通过import self from core-js-pure/stable/self显式导入验证的是无全局污染的模块导出形式其导出的self就是全局对象本身同样满足是对象与包含全局两个断言。Entry points如何在你的项目中引入web.self按照 docs/web/docs/features/web-standards/self.md 文档的说明web.self的入口点遵循 core-js 统一的入口点体系core-js(-pure)/stable|actual|full/self即以core-js全局版本或core-js-pure纯净版本为包名配合stable/actual/full三个特性级别均可直接按/self导入。结合 docs/web/docs/usage.md 对入口点体系的说明这三个级别的关系是stable仅包含稳定的 ES 与 Web 标准特性不含提案actualstable 之上再加入 Stage 3 提案官方推荐日常使用full全部特性含早期阶段提案。具体到web.self这一稳定 Web 标准特性三种级别均包含它。以实际代码为例// 方式一按需引入单个入口推荐 import core-js/stable/self; // 全局版本注入 self 全局属性 import self from core-js-pure/stable/self; // pure 版本导出 self 引用不污染全局 // 方式二引入整个 Web 标准特性集 import core-js/stable; // 全部稳定特性含 web.self import core-js/web; // 仅 Web 标准模块聚合在模块层面web.self通过两条路径被引用packages/core-js/stable/self.js 是独立入口它require(../modules/web.self)加载实现后从internals/path导出path.selfpackages/core-js/web/index.js 是 Web 标准聚合入口与web.atob、web.btoa、web.queue-microtask、web.url等模块一并加载。值得强调的是web.self属于扩展全局对象的特性应只在core-js全局版本下使用若使用core-js-pure的独立入口导入得到的是全局对象的引用并不会向全局注入self属性pure 版本的设计目标就是不污染全局命名空间。实战场景self的价值在哪里web.self模块的实际价值体现在跨环境脚本的统一性上Web Worker / Service Worker 环境这些环境没有window规范要求必须提供self。core-js 确保即使在怪异引擎中self也语义正确让浏览器通用脚本可以放心以self为全局锚点书写Node.js / Deno 等非浏览器环境Node 早于 ES2020 的版本没有globalThis和self而 Deno 曾有描述符不规范的缺陷见 web.self.js 内注释引用的 Deno issue。引入core-js/stable/self后self在这些运行时中也能指向全局对象使得同一份依赖self的代码可以跨浏览器与服务器端复用统一全局访问范式配合 packages/core-js/internals/global-this.js 中globalThis→window→self→global→this的探测链self在任意受支持环境中都可作为获取全局对象的可靠手段之一。小结从规范定义、polyfill 实现到入口点与测试web.self模块展示了一个成熟 polyfill 的完整形态通过能力检测区分两条实现路径以符合规范的 accessor 定义为主、简单赋值降级为辅并针对 Deno 等引擎的描述符缺陷做主动修复。理解这个模块你不仅能正确地在项目中引入core-js/stable/self或core-js(-pure)/.../self入口也能在需要以self为全局锚点的跨环境工程中做出可靠决策。// 最终验证引入后的 self 与全局对象完全一致 self.Array Array; // true self.Math Math; // true self globalThis; // true在现代标准环境中【免费下载链接】core-jsStandard Library项目地址: https://gitcode.com/GitHub_Trending/co/core-js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考