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

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

一.定义全局变量命名空间
只创建一个全局变量,并定义该变量为当前应用容器,把其他全局变量追加在该命名空间下
        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大应用的时候,你会发现不同的代码风格跟全局变量会导致很多冲突,这是一个很痛苦的事情。

曾经的经历

用过jQuery的人就知道其主要的变量符号就是$,没错!因此很多项目的开发人员也要学,就自己把$定义成别的含义了,我心里对其是无敌的鄙视跟厌恶。

我曾经拿过一个项目使用jquery的,然后上头要我使用一个已有的富文本编辑器,这样就有两个JS文件了

jquery.js和editor.js,于是我要开始写该页面的逻辑了,我发现editor.js里边自定义了$符号,我原本想要把它直接替换成别的标志符,但是悲剧的是,它还有一些插件也会用到,混乱的结构导致我花了很多时间去解决这个冲突。

全局Window

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

function test1(){
}  

var name;  

function test2(){
    i = 1;
}  

上边代码中的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 = 1;//定义这个包里边的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变量底下,这里只是一个示范。

本篇总结

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


本文转载自CSDN博客--
时间: 2024-10-11 00:11:02

防止js全局变量污染方法总结的相关文章

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

javaScript 可以随意定义保存所有应用资源的全局变量.但全局变量可以削弱程序灵活性,增大了模块之间的耦合性.在多人协作时,如果定义过多的全局变量 有可能造成全局变量冲突,也就是全局变量污染问题,以下是两种解决办法 一.定义全局变量命名空间只创建一个全局变量,并定义该变量为当前应用容器,把其他全局变量追加在该命名空间下 var MY={};my.name={big_name:"zhangsan",small_name:"lisi"};my.work={scho

js全局变量污染问题

javaScript 可以随意定义保存所有应用资源的全局变量.但全局变量可以削弱程序灵活性,增大了模块之间的耦合性.在多人协作时,如果定义过多的全局变量 有可能造成全局变量冲突,也就是全局变量污染问题,以下是两种解决办法 一.定义全局变量命名空间 只创建一个全局变量,并定义该变量为当前应用容器,把其他全局变量追加在该命名空间下 var MY={}; my.name={ big_name:"zhangsan", small_name:"lisi" }; my.work

nodejs 全局变量和方法,以及console使用

A.nodejs的console有很多种类型: console.log(1),console.error(2),console.dir(3),console.time(4),console.timeEnd(5),console.trace(6).console.asstert(7). 眼花了吧,哈哈哈,这里经过使用以后我觉得,似乎console.log,可以替代2,3.可能因为语义的缘故吧. a.console.dir()主要用来输出一个object的结构信息. b.console.time('

今天和组内一起写代码时碰到了一个关于命名冲突的问题,最后用js命名空间的方法解决的。

//第一步,首先创建一个全局变量,可以放在自己的js方法库中方便以后用,这个就是用来注册命名空间的方法. ns = function(namespace){ var arr = namespace.split('.');  //将传入的字符串如"com.test.lzn"以'.'隔开做成一个数组 var strNamespace = ""; //这个是为了保存每一步循环进去的包名 for(var i=0;i<arr.length;i++) { if(i!=0)

javascript 减少全局变量的方法和好处

以前我基于谷歌地图封装过一个很大型的船舶监控的JS插件.当时由于入行时间不够,加之经验不足,导致js写得不好,全局变量到处都是.到后面居然前面的会覆盖前面的全局变量.今天就来研究下使用太多全局变量导致的问题. 一.全局变量是如何产生的 我们知道全局变量都是挂载在window对象上面的.它的产生方式有很多种,下面就列出来. 1.人为定义的 人为定义很简单,你这样写的代码就定义了一个全局变量person: 1 2 3 <script type="text/javascript">

jquery easyui树的简答构造+动态生成js全局变量

jquery easyui树的简答构造: JSP页面 组织机构: <input id="p_organId" name="p_organId" style="width: 160px;height: 28px;"> function loadOrgan(){ organ_combotree = $("#p_organId").combotree({ url:'${ctxFront}/cust/tree', mult

js全局变量与局部变量 预解析与作用域链详解

局部变量和全局变量同名时,会隐藏这个全局变量: 4.变量 关键字: 4.变量 4.1 变量的类型 JS是松散类型的语言 4.2 变量的声明 var 声明是变量的标准声明 var 声明的变量是永久性的,不能用delete运算符删除 全局对象,调用对象初始化时,JS解析器会在相应的代码段里寻找var声明的变量, 然后在全局对象,调用对象中创建相应的属性,此时它是未赋值的(undefined), 当程序执行到相应的var声明代码段时才会给相应对象的属性赋值 重复的声明:根据以上var声明作用的理解,重

JQuery 加载 CSS、JS 文件的方法有哪些?

在进行web前端开发(http://www.maiziedu.com/course/web-px/)时,我们可能会需要使用JQuery加载一个外部的css文件或者js文件,加载外部文件的方法有多种,下面具体看看各种加载方法 JS 方式加载 CSS.JS 文件: //加载 css 文件function includeCss(filename) { var head = document.getElementsByTagName('head')[0]; var link = document.cre

js 变量提升+方法提升

<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <script type="text/javascript"> var a = 100; function t() { alert(a); var a = 10; } t(); //输出结果为undefine