写代码的时候,很多人图省事,随手就声明一个全局变量。比如在网页里做个计数器,直接写 window.counter = 0,后面谁要用都拿得到。短期看挺方便,时间一长,问题就来了。
全局变量多了,就像客厅堆满杂物
想象一下你家的客厅,本来是喝茶聊天的地方,结果慢慢变成了储物间:鞋子、快递盒、旧报纸全堆在这儿。想找一双拖鞋得翻半天,还容易踩到东西摔跤。全局变量太多,程序也一样乱。
多个脚本同时修改同一个全局变量时,谁改的、什么时候改的,很难追踪。比如你写了个 user 变量存登录信息,另一个同事写的弹窗功能也用了同名变量,结果登录状态莫名其妙变了,查半天才发现是名字撞了。
命名冲突不是偶然,而是早晚的事
尤其在多人协作或引入第三方库时,全局命名空间就像公共白板,谁都能往上写。jQuery 用 $,你也用 $ 写个自定义函数,页面一加载,其中一个就被覆盖了。这种 bug 不一定立刻暴露,可能上线几天后才出问题,定位起来特别头疼。
用作用域把变量“关”起来
JavaScript 提供了函数作用域和块级作用域,可以把变量限制在需要的地方。比如做个点击统计,没必要让整个页面都知道这个数字:
function initClickCounter(){
let count = 0;
document.getElementById('btn').addEventListener('click', function(){
count++;
console.log('点击了' + count + '次');
});
}
initClickCounter(); // 启动计数器
// 外部无法访问 count,不会污染全局
这里的 count 被“关”在函数里,只有按钮点击事件能访问,外面碰不着,自然不会被误改。
模块化是现代开发的标配
现在写前端,大多用 ES6 模块。每个文件就是一个独立空间,变量默认不对外暴露。要共享数据,明确导出和导入:
// counter.js
let count = 0;
export function increment(){
count++;
return count;
}
// main.js
import { increment } from './counter.js';
button.addEventListener('click', () => {
console.log(increment());
});
这样别人用你的功能时,清楚知道数据从哪来,也不会不小心改到内部状态。
IIFE 防止污染老项目
有些老项目没法一下子上模块化,可以用立即执行函数(IIFE)把代码包起来:
(function(){
var apiKey = 'abc123xyz'; // 不会被外部访问
function sendRequest(url){
fetch(url, {
headers: { 'Authorization': apiKey }
});
}
window.sendRequest = sendRequest; // 只暴露需要的
})();
这样一来,apiKey 安全地藏在里面,只有 sendRequest 能用它,不会被其他代码窥探或篡改。
少用全局变量,不是教条,而是让代码更容易维护。就像保持家里整洁,不是为了好看,是为了每天过得顺心。变量该藏就藏,该封就封,别图那一时痛快,给以后挖坑。