防止js全局变量污染方法总结

javaScript 可以随意定义保存所有应用资源的全局变量。但全局变量可以削弱程序灵活性,增大了模块之间的耦合性。
在多人协作时,如果定义过多的全局变量 有可能造成全局变量冲突,也就是全局变量污染问题,以下是两种解决办法

防止js全局变量污染方法

一.定义全局变量命名空间

只创建一个全局变量,并定义该变量为当前应用容器,把其他全局变量追加在该命名空间下

var MY={};
my.name={
    big_name:"zhangsan",
    small_name:"lisi"
};
my.work={
    school_work:"study",
    family_work:"we are"
};

二 . 利用匿名函数将脚本包裹起来

(function(){
    var exp={};
    var name="aa";
    exp.method=function(){
      return name;
  };
    window.ex=exp;
})();

前言

记得long long ago,刚刚开始写js的时候,我喜欢写一些函数在JS文件里边,然后通过script标签引进来,在DOM节点上绑定onclick等事件,看了很多人写的代码,也大多是这样。

后来会发现,当项目小的时候这么做为了快速开发是可以接受的,然而当很多人一起开发一个JavaScript大应用的时候,你会发现不同的代码风格跟全局变量会导致很多冲突,这是一个很痛苦的事情。

全局Window

我们都知道,在文件中直接定义的变量跟函数(不嵌套在任何域底下的)都是属于全局的,也就是都在当前页面的window变量底下。例如:

function test1(){
}  
 
var name;  
 
function test2(){
    i = ;
} 

上边代码中的name,test1,test2和i都是属于window底下的全局变量,也就是可以通过以下三种办法访问到它们:

1.直接访问name,test1()等;

2.使用window["name"], window['test1']()等;

3.使用window.name,window.test1()等。

注意:上边代码中的i虽然是在test2函数里边才出现的,因为其前面没有使用var关键字,解释器会认为它在test2的上一层定义的,依次查找上一层,直到找到window全局,如果发现还是未定义,那么将其挂在window底下成为了全局变量。

所以你直接定义的函数通通都挂到了window底下,这就是一种污染了,当很多人定义各种变量跟函数,你又得同时引入进来的时候,这个冲突的概率就变大了。

减少污染

那为了避免过多这样的冲突,以及模块之间的耦合性更低,需要减少这样的污染。

此时我们会想,那不要把变量定义在全局呗,采用类似C++的命名空间,Java的包的思路就行啦。

首先就是将不同的模块划入到不同的全局“包”(这里的包的概念实际上就是一个javascript对象而已)。

例如,程序员A为全局添加一个A变量,然后他把自己定义的函数/变量全部挂到A底下,这样就跟程序员B所定义的隔离了。

再者我们可以使用函数域来隔离一些局部变量的冲突,比如说程序员A写的代码如下:

(function(obj){
    /* 在这里边就与外边隔离了,定义的局部变量不会与外界干扰 */
    /* 为了跟外界达到共享的目的,还可以为其加入参数,例如obj,在最后调用的时候把相关的参数传进来,例如下边的window */  
 
    var A = {};//定义一个A包
    var tmp;//临时变量  
 
    A.i = ;//定义这个包里边的i变量
    A.func = function(){alert('I am A');};  
 
    obj.A = A;/* 把A包挂到obj底下 */  
 
})(window);  

当离开了这个函数域之后,tmp等局部变量被销毁(只要不要存在在闭包里边),程序员A定义的东西通通挂到了变量window.A底下,从而减少了很多污染,避免了不必要的冲突。

回到过去

再次回到刚刚提过的那个经历,如果我现在为editor.js整个包围在function里边,通过这种方式把$给隐藏在一个包里边,在它的其他控件中也采取这样的做法,当然还要做一小点改动:

/* editor.js */
(function(obj){
    /* 原先editor里边的内容 */
    /* 里边有定义了自己的$标志 */  
 
    obj.editor = obj.editor || {};//如果没有editor对象,则生成一个空对象
    obj.editor.$ = $;//把$挂在全局的editor对象上
})(window); 
/* 其他控件.js */
(function(obj){
    var $ = obj.$;//把$恢复  
 
    /* 原先控件的内容 */  
 
})(window.editor); 

当然咯,如果editor.js有些功能需要暴露到全局的话,还需要将其进一步的挂在editor变量底下,这里只是一个示范。

本篇总结

很多框架都采用了这种做法减少全局污染,可能很多人一开始对这种做法有疑惑,这里只是个人理解拿出来分享一下。

### JavaScript 中全局变量的使用及其最佳实践 #### 定义与作用域 全局变量是在函数外部声明或者在任何地方通过 `window` 对象访问到的变量。这些变量在整个程序生命周期内都存在,并且可以在脚本中的任意位置被读取或修改[^1]。 ```javascript // 全局变量定义方式一:直接赋值给未声明的变量会自动成为全局对象属性 var globalVar = 'I am a global variable'; function checkScope() { console.log(globalVar); // 可以在这里正常打印 } checkScope(); ``` #### 风险与挑战 过度依赖全局变量可能导致代码难以维护和调试,因为它们容易受到意外覆盖的影响。此外,在大型项目中过多的全局命名空间污染可能会引发冲突问题[^2]。 #### 最佳实践建议 为了减少潜在的风险并遵循现代Web开发的最佳做法: - **局部化范围**:尽可能将变量限定于最小的作用范围内;如果某个特定功能只需要在一个方法内部工作,则应该在那里创建该变量而不是作为全局成员。 - **立即执行函数表达式 (IIFE)** :利用闭包特性来封装逻辑从而避免不必要的暴露公共接口。 ```javascript (function(){ var privateVariable = "This won't leak!"; function innerFunction(){ /* ... */ } // Only expose what needs to be exposed. window.publicAPI = {}; })(); ``` - **模块模式** 和 ES6 的导入导出机制也是很好的选择,可以更好地管理依赖关系以及隔离不同部分之间的交互[^3]. - **严格模式** (`use strict`) 下不允许隐式的全局变量创建,这有助于防止无意间引入新的全局状态。 #### 性能考虑 虽然这里讨论的是性能优化而非直接关于全局变量本身,但是值得注意的是,频繁地从全局上下文中查找变量可能会影响效率。因此,对于那些经常使用的数据结构或是DOM节点引用来说,最好将其存储在一个更靠近实际操作的地方比如局部变量里。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值