• 防止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变量底下。例如:

    1. function test1(){  
    2. }  
    3.   
    4. var name;  
    5.   
    6. function test2(){  
    7.     i = 1;  
    8. }  

    上边代码中的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写的代码如下:

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

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

    回到过去

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

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

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

    本篇总结

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

  • 相关阅读:
    centos7安装YouCompleteMe,vim打造成C++的IDE
    java循环定时器@Scheduled的使用
    js使用“toFixed( )”保留小数点后两位
    linux小本
    解决Maven资源过滤问题
    在Maven普通项目上添加Web app的支持
    项目中添加lib依赖
    回顾Servlet
    Tomcat 中文乱码
    Initialization failed for 'https://start.spring.io' Please check URL
  • 原文地址:https://www.cnblogs.com/lxl57610/p/8414768.html
Copyright © 2020-2023  润新知