全局作用域应只暴露一个顶层命名空间对象(如window.MyApp),其余功能作为其属性;用IIFE封装私有逻辑并安全初始化嵌套结构;现代项目优先采用ES Module避免全局污染。

在全局作用域中避免命名空间污染,核心不是“不用全局”,而是“只放一个门把手,其余全关在里面”。直接声明 function utils() {} 或 var config = {...} 是最常见也最危险的污染方式;真正安全的做法是收敛、封装、显式暴露。
只暴露一个顶层命名空间对象
整个项目或库只向全局挂载一个有意义的标识符,比如 window.MyApp 或 window.AcmeSDK,所有功能都作为它的属性存在:
- ✅ 正确写法:
window.MyApp = window.MyApp || {};,再定义MyApp.date.format()、MyApp.api.post() - ❌ 避免写法:
function formatDate() {}、var apiBase = '/v1';、const validators = {...}; - 这样即使多人协作或引入多个脚本,也只可能冲突一次(比如两个库都用
MyApp),而不是几十个变量互相覆盖
用 IIFE 封装私有实现逻辑
立即执行函数表达式(IIFE)能创建独立作用域,把配置、缓存、工具函数等“藏起来”,只把真正需要对外调用的方法挂到命名空间上:
- 内部变量如
let token = 'abc'、const cache = new Map()完全不会泄露 - 可提前检查命名空间是否已存在:
if (!window.MyApp) window.MyApp = {}; - 推荐兼容写法:
(function (global) { global.MyApp = MyApp; })(typeof window !== 'undefined' ? window : globalThis);
支持嵌套结构与空值防护
命名空间不是扁平列表,而是可逐层构建的树状结构,但每层访问前需确保上级存在:
立即学习“Java免费学习笔记(深入)”;
- 手动安全写法:
MyApp.ui = MyApp.ui || {};,再定义MyApp.ui.modal = {...} - 或封装一个工具函数:
function namespace(path) { /* 自动创建 window.MyApp.data.cache */ } - 调用
MyApp.data.cache.get()前,应确认MyApp.data.cache已初始化,否则报错而非静默失败
现代项目优先走 ES Module 路线
IIFE 和命名空间是过渡方案,适合无构建工具的老环境;新项目应直接采用原生模块机制:
- 每个
.js文件默认是独立作用域,顶层const/function不会自动变成全局变量 - 用
export明确导出接口,用import显式引入依赖,边界清晰、可静态分析 - HTML 中启用:
<script type="module" src="main.js"></script> - 若仍需提供全局入口(如 SDK),可用模块打包后统一挂载,而非手写全局逻辑


















