避免全局污染的核心是只暴露一个可控入口,用let/const、IIFE、命名空间或ES Module将逻辑封装在私有作用域内,禁用隐式全局变量。

避免 JavaScript 全局作用域污染,核心是不让变量、函数或对象直接挂到 window(浏览器)或 global(Node.js)上。关键不在于“完全不用全局”,而在于“只暴露一个可控入口”,把其余逻辑收束在私有边界内。
用 let/const 声明循环和块级变量
var 声明的循环变量会提升并泄露到函数甚至全局作用域,导致意外访问和闭包错误:
-
不要写:
for (var i = 0; i console.log(i), 0); }—— 输出全是3 -
改用:
for (let i = 0; i console.log(i), 0); }—— 每次迭代绑定独立的i,输出0, 1, 2 -
for...of和for...in配合let同样安全,变量生命周期严格限定在每次循环块内
用 IIFE 封装初始化逻辑
立即执行函数表达式能创建私有作用域,内部变量不会逃逸,适合老项目或无构建工具环境:
- 基础写法:
(function () { const config = { api: '/v1' }; function init() { /* ... */ } })();——config和init完全不可见 - 安全挂载命名空间:
(function (global) { if (!global.MyApp) global.MyApp = {}; global.MyApp.utils = { formatDate() { /* ... */ } }; })(typeof window !== 'undefined' ? window : global); - 开头加
"use strict";可防止隐式全局(如忘记写var/let/const就赋值)
用命名空间对象统一收敛暴露点
不禁止用全局,但只允许一个顶层标识符,所有功能都作为其属性存在:
- 错误方式:
function validateEmail() { ... }、const API_URL = '...';—— 直接污染两个全局名 - 推荐方式:
window.Acme = window.Acme || {};,然后Acme.validation = { isEmail() { ... } };、Acme.config = { apiUrl: '...' }; - 支持嵌套:用
Acme.ui = Acme.ui || {};或封装ns('Acme.data.cache')自动建多层对象,调用前检查是否存在
优先采用 ES Module 真实解耦
命名空间只是缓解手段,ES Module 才是现代项目的标准解法:
- 每个文件默认是独立模块作用域,
const、function不会自动上浮到全局 - 显式导出:
export function debounce(fn, ms) { ... };显式导入:import { debounce } from './utils.js'; - 打包工具(Vite/Webpack)能静态分析依赖,自动合并、摇树、提升作用域,比手动命名空间更可靠
- 搭配 TypeScript 还能提前捕获类型误用和未声明变量问题


















