动态加载的 script 标签不自动共享作用域但共用全局 window,变量能否访问取决于声明方式(var 挂全局,let/const 不挂)和执行时序;常见报错主因是时序错误或非全局声明,安全做法是显式挂载命名空间、Promise 控制顺序或改用模块隔离。

动态加载的 script 标签之间**不自动共享作用域**,但它们默认共享全局作用域(window),前提是执行时机正确、变量声明方式得当。关键不在“是否能共享”,而在“如何安全、可控地共享”——本质是管理全局暴露和执行顺序。
动态加载脚本的全局作用域是同一片环境
无论 script 是静态写死在 HTML 里,还是用 document.createElement('script') 动态插入,只要最终执行在同一个页面上下文,它们就共用同一个 window 对象。这意味着:
-
var utils = { log() { console.log('ok') } };在第一个动态脚本中执行后,第二个动态脚本可直接调用utils.log() -
function initApp() { ... }声明后,后续任意动态脚本都能调用它 - 但
let config = {}或const api = 'v1'不会挂到window,后续脚本无法访问
常见失效原因:不是作用域问题,而是时序与声明方式问题
报 undefined 或 not defined,90% 情况下不是作用域隔离导致的,而是:
- 后加载的脚本尝试调用前一个脚本里的
let/const变量 → 这些变量根本没进全局,自然找不到 - 脚本 A 动态加载后立即执行,但脚本 B 还在下载或解析中 → 调用未定义函数
- 多个脚本都用
var store = {},后者覆盖前者,逻辑被静默破坏 - 没处理
onload回调,误以为插入即可用
推荐的安全共享方式:显式、命名空间化、带加载控制
不要依赖隐式全局,而是主动设计共享契约:
- 统一挂载到命名空间:
window.MyApp = window.MyApp || {};,再往里面加MyApp.api、MyApp.utils - 用
Promise链确保执行顺序:loadScript('a.js').then(() => loadScript('b.js')) - 在目标脚本末尾主动触发事件,通知依赖方:“我准备好了”:
window.dispatchEvent(new CustomEvent('a:ready')) - 避免
var,改用Object.defineProperty(window, 'CONFIG', { value: {}, writable: false })防篡改
彻底隔离?那就别共享——用模块或 IIFE
如果业务逻辑本就不该耦合,强行共享反而埋雷。这时应反向思考:
- 把动态加载的脚本设为
type="module",天然隔离,必须export/import - 用 IIFE 包裹整个脚本内容:
(function() { const privateVar = 1; window.PublicAPI = { get() { return privateVar; } }; })(); - 现代项目优先走构建工具链(Vite/Webpack),让模块系统接管依赖,而不是手写跨 script 调用
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











