闭包本身不直接实现“总线”或“授权机制”,它仅提供变量私有化与状态持久化的基础能力;所谓“单向授权总线”,本质是主窗口主动暴露有限、受控接口给子窗口,且子窗口无法反向访问或修改主窗口内部状态。

闭包本身不直接实现“总线”或“授权机制”,它只是提供变量私有化与状态持久化的基础能力。所谓“单向授权总线”,本质是**主窗口主动暴露有限、受控的接口给子窗口,且子窗口无法反向访问或修改主窗口内部状态**。闭包在这里的作用,是封装主窗口的授权逻辑和可调用能力,防止子窗口绕过限制直接操作全局或 DOM。
核心设计思路:主窗口定义授权白名单 + 闭包隔离执行上下文
主窗口(parent)通过一个立即执行函数(IIFE)创建闭包,在其中声明:
– 可被子窗口调用的方法集合(如 openModal、notify、getUserId);
– 一套校验规则(比如只允许特定 origin 的子窗口调用);
– 不对外暴露任何内部状态变量(如 token、config、dom 引用)。
子窗口(child)只能通过 window.opener?.postMessage 发送请求,主窗口监听 message 事件,再由闭包内的授权函数决定是否执行、返回什么结果。
具体实现步骤
- 主窗口初始化闭包总线:在页面加载后,执行 IIFE,生成带校验的接口对象,并绑定到 window.bus 或直接挂载到 window 上(仅限信任环境)
- 定义白名单方法:每个方法都做 origin 校验、参数类型检查、副作用防护(例如 openModal 不接受任意 HTML 字符串,只接受预设 type 和 data)
- 子窗口发起调用需带签名:发送 postMessage 时附带 { type: 'openModal', https://www.php.cn/link/84094c9f8dc82c57cae08d3cd0acb96f: { type: 'alert' }, nonce: 'xxx' },主窗口比对 nonce 或使用简单时间戳+哈希防重放(视安全等级而定)
- 响应必须异步且单向:主窗口不直接 return,而是用另一个 postMessage 回传结果,子窗口监听自身 message 事件接收;避免同步调用导致阻塞或跨域报错
关键代码结构示意
主窗口中:
const Bus = (function() {
const allowedOrigins = ['https://app.example.com', 'https://staging.example.com'];
const methods = {
openModal({ type, title }) {
if (!['alert', 'confirm'].includes(type)) throw new Error('Invalid modal type');
// 实际打开逻辑,完全封闭在闭包内
return { success: true };
},
getUserId() {
return { id: 'usr_abc123' }; // 只读脱敏数据
}
};
<p>window.addEventListener('message', (e) => {
if (!allowedOrigins.includes(e.origin)) return;
const { action, https://www.php.cn/link/84094c9f8dc82c57cae08d3cd0acb96f } = e.data || {};
if (typeof methods[action] === 'function') {
try {
const result = methods<a href="https://www.php.cn/link/84094c9f8dc82c57cae08d3cd0acb96f">action</a>;
e.source.postMessage({ action, result }, e.origin);
} catch (err) {
e.source.postMessage({ action, error: err.message }, e.origin);
}
}
});</p><p>return { init: () => {} }; // 无须导出实例,闭包已生效
})();</p>
为什么不能靠闭包“自动授权”
闭包解决不了跨窗口通信的天然隔离问题。window.opener 是浏览器强制的引用限制,子窗口能拿到 opener 但无法直接调用其函数(尤其跨域时会抛 SecurityError)。真正起作用的是:
– postMessage 的显式通道;
– 闭包封装的校验与执行逻辑;
– 主窗口主动选择暴露什么、拒绝什么。
闭包只是让这个“选择”不被篡改、不被外部变量污染。










