[1]工程师甲编写功能A

  1. var a = 1;
  2. var b = 2;
  3. alert(a+b);//

[2]工程师乙添加新功能B

  1. var a = 2;
  2. var b = 1;
  3. alert(a-b);//

[3]上一步中,工程师乙在不知情的情况下,定义了同名变量a,产生冲突。于是使用匿名函数将脚本包起来,让变量作用域控制在匿名函数之内。

  1. //功能A
  2. (function(){
  3.   var a = 1;
  4.   var b = 2;
  5.   alert(a+b);//
  6. })();
  7. //功能B
  8. (function(){
  9.   var a = 2;
  10.   var b = 1;
  11.   alert(a-b);//
  12. })();

[4]此时有了新需求,网页中加入功能C,且需要用到功能A中的变量b。于是在window作用域下定义一个全局变量,把它作为一个桥梁,完成各匿名函数之间的通信

  1. //全局变量
  2. var str;
  3. //功能A
  4. (function(){
  5.   var a = 1;
  6.   //将b的值赋给str
  7.   var b = str = 2;
  8.   alert(a+b);//
  9. })();
  10. //功能B
  11. (function(){
  12.   var a = 2;
  13.   var b = 1;
  14.   alert(a-b);//
  15. })();
  16. //功能C
  17. (function(){
  18.   //将str的值赋给b
  19.   var b = str;
  20.   alert(b);//
  21. })();

[5]但如果功能C还需要功能A中的变量a呢,这时就需要再定义一个全局变量

  1. //全局变量
  2. var str,str1;
  3. //功能A
  4. (function(){
  5.   //将a的值赋给str1
  6.   var a = str1 = 1;
  7.   //将b的值赋给str
  8.   var b = str = 2;
  9.   alert(a+b);//
  10. })();
  11. //功能B
  12. (function(){
  13.   var a = 2;
  14.   var b = 1;
  15.   alert(a-b);//
  16. })();
  17. //功能C
  18. (function(){
  19.   //将str1的值赋给a
  20.   var a = str1;
  21.   //将str的值赋给b
  22.   var b = str;
  23.   alert(a*b);//
  24. })();

[6]但随着匿名函数之间需要通信的变量越多,需要的全局变量也就越多。因此需要严格控制全局变量的数量,使用hash对象作为全局变量,可以将需要的变量都作为对象的属性,可以保证全局变量的个数足够少,同时拓展性非常好

  1. //全局变量
  2. var GLOBAL = {};
  3. //功能A
  4. (function(){
  5.   //将a的值赋给GLOBAL.str1
  6.   var a = GLOBAL.str1 = 1;
  7.   //将b的值赋给GLOBAL.str
  8.   var b = GLOBAL.str = 2;
  9.   alert(a+b);//
  10. })();
  11. //功能B
  12. (function(){
  13.   var a = 2;
  14.   var b = 1;
  15.   alert(a-b);//
  16. })();
  17. //功能C
  18. (function(){
  19.   //将GLOBAL.str1的值赋给a
  20.   var a = GLOBAL.str1;
  21.   //将GLOBAL.str的值赋给b
  22.   var b = GLOBAL.str;
  23.   alert(a*b);//
  24. })();

[7]但如果新增功能D,功能D需要和功能B通信,并使用功能B脚本中的变量a,开发功能D的是工程师丁

  1. //全局变量
  2. var GLOBAL = {};
  3. //功能A
  4. (function(){
  5.   //将a的值赋给GLOBAL.str1
  6.   var a = GLOBAL.str1 = 1;
  7.   //将b的值赋给GLOBAL.str
  8.   var b = GLOBAL.str = 2;
  9.   alert(a+b);//
  10. })();
  11. //功能B
  12. (function(){
  13.   //将a的值赋给GLOBAL.str1
  14.   var a = GLOBAL.str1 = 2;
  15.   var b = 1;
  16.   alert(a-b);//
  17. })();
  18. //功能C
  19. (function(){
  20.   //将GLOBAL.str1的值赋给a
  21.   var a = GLOBAL.str1;
  22.   //将GLOBAL.str的值赋给b
  23.   var b = GLOBAL.str;
  24.   alert(a*b);//
  25. })();
  26. //功能D
  27. (function(){
  28.   //将GLOBAL.str1的值赋给a
  29.   var a = GLOBAL.str1;
  30.   alert(a*2);//
  31. })();

[8]由于工程师丁只关心自己的匿名函数和功能B的匿名函数,使用GLOBAL.str却无意中覆盖了功能A中设置的同名变量,导致功能C出错。于是使用命名空间来解决这个问题,在不同的匿名函数下,根据功能声明一个不同的命名空间,然后每个匿名函数中的GLOBAL对象的属性都不要直接挂在GLOBAL对象上,而是挂在此匿名函数的命名空间下

  1. //全局变量
  2. var GLOBAL = {};
  3. //功能A
  4. (function(){
  5.   GLOBAL.A = {};
  6.   //将a的值赋给GLOBAL.A.str1
  7.   var a = GLOBAL.A.str1 = 1;
  8.   //将b的值赋给GLOBAL.A.str
  9.   var b = GLOBAL.A.str = 2;
  10.   alert(a+b);//
  11. })();
  12. //功能B
  13. (function(){
  14.   GLOBAL.B = {};
  15.   //将a的值赋给GLOBAL.B.str1
  16.   var a = GLOBAL.B.str1 = 2;
  17.   var b = 1;
  18.   alert(a-b);//
  19. })();
  20. //功能C
  21. (function(){
  22.   //将GLOBAL.A.str1的值赋给a
  23.   var a = GLOBAL.A.str1;
  24.   //将GLOBAL.A.str的值赋给b
  25.   var b = GLOBAL.A.str;
  26.   alert(a*b);//
  27. })();
  28. //功能D
  29. (function(){
  30.   //将GLOBAL.B.str1的值赋给a
  31.   var a = GLOBAL.B.str1;
  32.   alert(a*2);//
  33. })();

[9]如果同一个匿名函数中的程序非常复杂,变量名很多,命名空间还可以进一步拓展,生成二级命名空间

  1. //以功能A为例
  2. (function(){
  3.   var a = 1, b = 2;
  4.   GLOBAL.A = {};
  5.   GLOBAL.A.CAT = {};
  6.   GLOBAL.A.DOG = {};
  7.   GLOBAL.A.CAT.name = 'mimi';
  8.   GLOBAL.A.DOG.name = 'xiaobai';
  9.   GLOBAL.A.CAT.move = function(){};
  10.   GLOBAL.A.str1 = a;
  11.   GLOBAL.B.str = b;
  12. })();

[10]因为生成命名空间是个非常常用的功能,进一步将生成命名空间的功能定义成一个函数,方便调用,完整版本改写后的代码如下

  1. var GLOBAL = {};
  2. GLOBAL.namespace = function(str){
  3.   var arr = str.split('.');
  4.   var o = GLOBAL;
  5.   var start = 0;
  6.   if(arr[0] == 'GLOBAL'){
  7.     start = 1;
  8.   }else{
  9.     start = 0;
  10.   }
  11.   for(var i = start; i < arr.length; i++){
  12.     o[arr[i]] = o[arr[i]] || {};
  13.     o = o[arr[i]];
  14.   }
  15. };
  16. //功能A
  17. (function(){
  18.   var a = 1;
  19.   var b = 2;
  20.   GLOBAL.namespace('A.CAT');
  21.   GLOBAL.namespace('A.DOG');
  22.   GLOBAL.A.CAT.name = 'mimi';
  23.   GLOBAL.A.DOG.name = 'xiaobai';
  24.   GLOBAL.A.CAT.move = function(){};
  25.   GLOBAL.A.str1 = a;
  26.   GLOBAL.A.str = b;
  27.   alert(a+b);//
  28. })();
  29. //功能B
  30. (function(){
  31.   var a = 2;
  32.   var b = 1;
  33.   GLOBAL.namespace('B');
  34.   GLOBAL.B.str1 = a;
  35.   alert(a-b);//
  36. })();
  37. //功能C
  38. (function(){
  39.   var a = GLOBAL.A.str1;
  40.   var b = GLOBAL.A.str;
  41.   alert(a*b);//
  42. })();
  43. //功能D
  44. (function(){
  45.   var a = GLOBAL.B.str1;
  46.   alert(a*2);//
  47. })();

[11]代码的冲突问题已经解决了,但可维护性并不强。比如,现在需要让工程师甲去修改功能B。因为工程师甲写的脚本是关于功能A的,他并不知道功能B的脚本情况。为了改善这种局面,需要给代码添加适当的注释。

  1. var GLOBAL = {};
  2. GLOBAL.namespace = function(str){
  3.   var arr = str.split('.');
  4.   var o = GLOBAL;
  5.   var start = 0;
  6.   if(arr[0] == 'GLOBAL'){
  7.     start = 1;
  8.   }else{
  9.     start = 0;
  10.   }
  11.   for(var i = start; i < arr.length; i++){
  12.     o[arr[i]] = o[arr[i]] || {};
  13.     o = o[arr[i]];
  14.   }
  15. };
  16. /*
  17. * @method 功能A:实现加法运算
  18. * @author 工程师甲
  19. * @connect 1234567
  20. * @time 2015-01-01
  21. */
  22.  
  23. (function(){
  24.   var a = 1;
  25.   var b = 2;
  26.   GLOBAL.namespace('A.CAT');
  27.   GLOBAL.namespace('A.DOG');
  28.   GLOBAL.A.CAT.name = 'mimi';
  29.   GLOBAL.A.DOG.name = 'xiaobai';
  30.   GLOBAL.A.CAT.move = function(){};
  31.   GLOBAL.A.str1 = a;
  32.   GLOBAL.A.str = b;
  33.   alert(a+b);//
  34. })();
  35. /*
  36. * @method 功能B:实现减法运算
  37. * @author 工程师乙
  38. * @connect 1234567
  39. * @time 2015-01-01
  40. */
  41. (function(){
  42.   var a = 2;
  43.   var b = 1;
  44.   GLOBAL.namespace('B');
  45.   GLOBAL.B.str1 = a;
  46.   alert(a-b);//
  47. })();
  48. /*
  49. * @method 功能C:实现乘法运算
  50. * @author 工程师丙
  51. * @connect 1234567
  52. * @time 2015-01-01
  53. */
  54. (function(){
  55.   var a = GLOBAL.A.str1;
  56.   var b = GLOBAL.A.str;
  57.   alert(a*b);//
  58. })();
  59. /*
  60. * @method 功能D:实现乘2运算
  61. * @author 工程师丁
  62. * @connect 1234567
  63. * @time 2015-01-01
  64. */
  65. (function(){
  66.   var a = GLOBAL.B.str1;
  67.   alert(a*2);//
  68. })();

让javascript不再冲突,需要

  •   [1]避免全局变量的泛滥
  •   [2]合理使用命名空间
  •   [3]为代码添加必要的注释

js避免命名冲突的更多相关文章

  1. js文件命名冲突理解

    在一个index.html文件里先后导入a.js和b.js文件a.js文件里写上var s = 2;console.log(s);b.js文件里写上var s = 5;这时a.js和b.js用了相同的 ...

  2. JS的解析与执行过程—全局预处理阶段之命名冲突的处理策略

    有如下代码: <body> <script> alert(f); function f() { console.log("fff"); } var f = ...

  3. Jquery库及其他库之间的$命名冲突解决办法

    首先我们应该知道,在jquery中,$(美元符号)就是jquery的别名,也就是说使用$和使用jquery是一样的,在很多时候我们命名空间时,正是因为这个$而产生的冲突的发生.比如说:$('#xmla ...

  4. javascript 闭包暴露句柄和命名冲突的解决方案

    暴露 最近在琢磨前端Js开源项目的东西,然后就一直好奇他们是怎么句柄暴露出来的,特整理一下两种方法. 将对象悬挂到window下面. 不使用var进行变量声明.下面上代码: (function(win ...

  5. JavaScript发展史,与JScript差别,引入方式,数据类型,命名规范,命名推荐,解决命名冲突

    文件夹: 1.JavaScript发展史 2.JavaScript与JScript差别 3.JavaScript引入方式 4.JavaScript基本数据类型及布尔值 5.JavaScript命名规范 ...

  6. jquery源码中noConflict(防止$和jQuery的命名冲突)的实现原理

    jquery源码中noConflict(防止$和jQuery的命名冲突)的实现原理 最近在看jquery源码分析的视频教学,希望将视频中学到的知识用博客记录下来,更希望对有同样对jquery源码有困惑 ...

  7. css命名冲突解决方法

    css的命名冲突目前有几种解决方法: 1.命名约定 人为的制定一下命名规则以避免冲突,例如前缀,嵌套等 2.CSS in JS 在JavaScript中写CSS,使用工具编译为css,最常见的是sty ...

  8. css 命名冲突 & solution

    css 命名冲突 & solution 类似这样,为了解决模块间可能存在的 css 命名冲突问题,需要单独提供给模块开发者一套模块开发环境:同时,文档上要有如何使用的规范说明. CSS 建议: ...

  9. js的命名规范

                   js的命名规范   1.驼峰命名法:首字母是小写的,接下来的字母都以大写字符开头.例如: var testValue = 0; var oneValue = 10; 2. ...

随机推荐

  1. matlab 学习之常用函数2

    -----------------------------author:midu ---------------------------qq:1327706646 ------------------ ...

  2. 【Android】带底部指示的自定义ViewPager控件

    在项目中经常需要使用轮转广告的效果,在android-v4版本中提供的ViewPager是一个很好的工具,而一般我们使用Viewpager的时候,都会选择在底部有一排指示物指示当前显示的是哪一个pag ...

  3. django使用自己的setting的方法

    创建一个自己的setting xxx.setting export DJANGO_SETTINGS_MODULE="xxx.setting" 然后在项目中import原生的sett ...

  4. java 对象变量 c++对象指针 初始化对象变量的2中方法

    java 对象变量 c++对象指针 java null引用 c++ null指针 Date deadline  是 对象变量,它可以引用Date类型的对象,但它不是一个对象,实际上它也没有引用对象. ...

  5. 使用cocos2d-js-3.0RC1中的物理引擎chipmunk模拟的“别碰钉子”源码分享(含碰撞检测)

    分别用box2d和chipmunk实现了一下,不过box2d没整理,也懒得整理了.chipmunk整理了一下,分享给大家吧. 刚开始研究,抛砖引玉 简要说明:1.初始化物理环境,增加边界 initPh ...

  6. php调用短网址接口

    <?php $ch=curl_init(); curl_setopt($ch,CURLOPT_URL,"http://dwz.cn/create.php"); curl_se ...

  7. 【题解】cycle

    [题解]cycle 题目描述 给定一个无向图,求一个环,使得环内边权\(\div\)环内点数最大. 数据范围 \(n \le 5000\) \(m\le 10000\) \(Solution\) 考虑 ...

  8. 爬虫之重要的requests模块

    一 . requests模块 什么是requests模块 requests模块是python中原生的基于网络请求的模块,其主要作用是用来模拟浏览器发起请求.功能强大,用法简洁高效.在爬虫领域中占据着半 ...

  9. iOS 开发实践之 Auto Layout

    原:http://xuexuefeng.com/autolayout/?utm_source=tuicool 本文是博主 iOS 开发实践系列中的一篇,主要讲述 iOS 中 Auto Layout(自 ...

  10. Android Weekly Notes Issue #319

    Android Weekly Issue #319 July 22nd, 2018. Android Weekly Issue #319 本期内容包括: MotionLayout加动画; Kotlin ...