实例讲解避免javascript冲突的方法

作者:异步漫步

时间:2026-10-30

浏览:413

本文通过具体实例演示了JavaScript中变量冲突的产生原因及解决方案。从使用匿名函数隔离作用域,到利用全局变量通信,再到引入Hash对象和命名空间管理,逐步解决变量覆盖与维护难题。文章最后总结了避免冲突的三大核心策略,帮助开发者编写更健壮、易维护的代码。

文章目录

本文通过具体实例,详细解析了如何在JavaScript开发中有效避免变量与函数冲突,供相关技术人员参考。

匿名函数隔离作用域

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


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

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


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

[3]在上述步骤中,工程师乙在不知情的情况下定义了与功能A同名的变量a,从而引发冲突。为解决此问题,可采用匿名函数将脚本包裹起来,将变量的作用域限制在匿名函数内部。


//功能A
(function(){
  var a = 1;
  var b = 2;
  alert(a+b);//3
})();
//功能B
(function(){
  var a = 2;
  var b = 1;
  alert(a-b);//1
})();


全局变量通信与局限

[4]此时出现新需求,网页需加入功能C,且该功能需要调用功能A中的变量b。为此,可在window作用域下定义一个全局变量,将其作为桥梁,实现各匿名函数之间的数据通信。


//全局变量
var str;
//功能A
(function(){
  var a = 1;
  //将b的值赋给str
  var b = str = 2;
  alert(a+b);//3
})();
//功能B
(function(){
  var a = 2;
  var b = 1;
  alert(a-b);//1
})();
//功能C
(function(){
  //将str的值赋给b
  var b = str;
  alert(b);//2
})();

[5]然而,若功能C还需要访问功能A中的变量a,则必须再定义一个独立的全局变量。


//全局变量
var str,str1;
//功能A
(function(){
  //将a的值赋给str1
  var a = str1 = 1;
  //将b的值赋给str
  var b = str = 2;
  alert(a+b);//3
})();
//功能B
(function(){
  var a = 2;
  var b = 1;
  alert(a-b);//1
})();
//功能C
(function(){
  //将str1的值赋给a
  var a = str1;
  //将str的值赋给b
  var b = str;
  alert(a*b);//2
})(); 

Hash对象管理全局变量

[6]随着匿名函数间需要通信的变量增多,所需的全局变量数量也会随之增加。因此,必须严格控制全局变量的数量。建议使用Hash对象作为全局变量容器,将所需变量作为该对象的属性,这样既能保证全局变量数量最少,又具备极佳的拓展性。


//全局变量
var GLOBAL = {};
//功能A
(function(){
  //将a的值赋给GLOBAL.str1
  var a = GLOBAL.str1 = 1;
  //将b的值赋给GLOBAL.str
  var b = GLOBAL.str = 2;
  alert(a+b);//3
})();
//功能B
(function(){
  var a = 2;
  var b = 1;
  alert(a-b);//1
})();
//功能C
(function(){
  //将GLOBAL.str1的值赋给a
  var a = GLOBAL.str1;
  //将GLOBAL.str的值赋给b
  var b = GLOBAL.str;
  alert(a*b);//2
})();

[7]若新增功能D,且功能D需与功能B通信,并使用功能B脚本中的变量a,而开发功能D的是工程师丁。


//全局变量
var GLOBAL = {};
//功能A
(function(){
  //将a的值赋给GLOBAL.str1
  var a = GLOBAL.str1 = 1;
  //将b的值赋给GLOBAL.str
  var b = GLOBAL.str = 2;
  alert(a+b);//3
})();
//功能B
(function(){
  //将a的值赋给GLOBAL.str1
  var a = GLOBAL.str1 = 2;
  var b = 1;
  alert(a-b);//1
})();
//功能C
(function(){
  //将GLOBAL.str1的值赋给a
  var a = GLOBAL.str1;
  //将GLOBAL.str的值赋给b
  var b = GLOBAL.str;
  alert(a*b);//2
})();
//功能D
(function(){
  //将GLOBAL.str1的值赋给a
  var a = GLOBAL.str1;
  alert(a*2);//4
})(); 

命名空间解决变量覆盖

[8]由于工程师丁仅关注自己的匿名函数与功能B的匿名函数,在使用GLOBAL.str时,可能无意中覆盖了功能A中设置的同名变量,导致功能C出错。此时,应使用命名空间来解决此问题:在不同的匿名函数下,根据功能声明不同的命名空间,并将每个匿名函数中GLOBAL对象的属性挂载到该匿名函数的命名空间下,而非直接挂在GLOBAL对象上。


//全局变量
var GLOBAL = {};
//功能A
(function(){
  GLOBAL.A = {};
  //将a的值赋给GLOBAL.A.str1
  var a = GLOBAL.A.str1 = 1;
  //将b的值赋给GLOBAL.A.str
  var b = GLOBAL.A.str = 2;
  alert(a+b);//3
})();
//功能B
(function(){
  GLOBAL.B = {};
  //将a的值赋给GLOBAL.B.str1
  var a = GLOBAL.B.str1 = 2;
  var b = 1;
  alert(a-b);//1
})();
//功能C
(function(){
  //将GLOBAL.A.str1的值赋给a
  var a = GLOBAL.A.str1;
  //将GLOBAL.A.str的值赋给b
  var b = GLOBAL.A.str;
  alert(a*b);//2
})();
//功能D
(function(){
  //将GLOBAL.B.str1的值赋给a
  var a = GLOBAL.B.str1;
  alert(a*2);//4
})(); 

[9]若同一匿名函数内的程序逻辑复杂且变量众多,命名空间可进一步拓展,生成二级命名空间。


//以功能A为例
(function(){
  var a = 1, b = 2;
  GLOBAL.A = {};
  GLOBAL.A.CAT = {};
  GLOBAL.A.DOG = {};
  GLOBAL.A.CAT.name = 'mimi';
  GLOBAL.A.DOG.name = 'xiaobai';
  GLOBAL.A.CAT.move = function(){};
  GLOBAL.A.str1 = a;
  GLOBAL.B.str = b;  
})();


[10]鉴于生成命名空间是常见需求,可将其封装为一个函数以便调用,完整版本改写后的代码如下。


var GLOBAL = {};
GLOBAL.namespace = function(str){
  var arr = str.split('.');
  var o = GLOBAL;
  var start = 0;
  if(arr[0] == 'GLOBAL'){
    start = 1;
  }else{
    start = 0;
  }
  for(var i = start; i < arr.length; i++){
    o[arr[i]] = o[arr[i]] || {};
    o = o[arr[i]];
  }
};
//功能A
(function(){
  var a = 1;
  var b = 2;
  GLOBAL.namespace('A.CAT');
  GLOBAL.namespace('A.DOG');
  GLOBAL.A.CAT.name = 'mimi';
  GLOBAL.A.DOG.name = 'xiaobai';
  GLOBAL.A.CAT.move = function(){};
  GLOBAL.A.str1 = a;
  GLOBAL.A.str = b;  
  alert(a+b);//3
})();
//功能B
(function(){
  var a = 2;
  var b = 1;
  GLOBAL.namespace('B');
  GLOBAL.B.str1 = a;
  alert(a-b);//1
})();
//功能C
(function(){
  var a = GLOBAL.A.str1;
  var b = GLOBAL.A.str;
  alert(a*b);//2
})();
//功能D
(function(){
  var a = GLOBAL.B.str1;
  alert(a*2);//4
})();


[11]虽然代码冲突问题已解决,但可维护性依然较弱。例如,若需让工程师甲修改功能B,由于他编写的脚本仅涉及功能A,并不了解功能B的具体情况。为改善这一局面,需为代码添加适当的注释。


var GLOBAL = {};
GLOBAL.namespace = function(str){
  var arr = str.split('.');
  var o = GLOBAL;
  var start = 0;
  if(arr[0] == 'GLOBAL'){
    start = 1;
  }else{
    start = 0;
  }
  for(var i = start; i < arr.length; i++){
    o[arr[i]] = o[arr[i]] || {};
    o = o[arr[i]];
  }
};
/*
* @method 功能A:实现加法运算
* @author 工程师甲
* @connect 1234567
* @time 2015-01-01
*/

(function(){
  var a = 1;
  var b = 2;
  GLOBAL.namespace('A.CAT');
  GLOBAL.namespace('A.DOG');
  GLOBAL.A.CAT.name = 'mimi';
  GLOBAL.A.DOG.name = 'xiaobai';
  GLOBAL.A.CAT.move = function(){};
  GLOBAL.A.str1 = a;
  GLOBAL.A.str = b;  
  alert(a+b);//3
})();
/*
* @method 功能B:实现减法运算
* @author 工程师乙
* @connect 1234567
* @time 2015-01-01
*/
(function(){
  var a = 2;
  var b = 1;
  GLOBAL.namespace('B');
  GLOBAL.B.str1 = a;
  alert(a-b);//1
})();
/*
* @method 功能C:实现乘法运算
* @author 工程师丙
* @connect 1234567
* @time 2015-01-01
*/
(function(){
  var a = GLOBAL.A.str1;
  var b = GLOBAL.A.str;
  alert(a*b);//2
})();
/*
* @method 功能D:实现乘2运算
* @author 工程师丁
* @connect 1234567
* @time 2015-01-01
*/
(function(){
  var a = GLOBAL.B.str1;
  alert(a*2);//4
})();


避免冲突的核心策略

让javascript不再冲突,需要

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

以上就是本文的详细内容,希望对大家的学习有所帮助。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章