如何避免javascript中的冲突
[1]工程师甲编写功能A
var a = 1;
var b = 2;
alert(a+b);//
[2]工程师乙添加新功能B
var a = 2;
var b = 1;
alert(a-b);//
[3]上一步中,工程师乙在不知情的情况下,定义了同名变量a,产生冲突。于是使用匿名函数将脚本包起来,让变量作用域控制在匿名函数之内。
//功能A
(function(){
var a = 1;
var b = 2;
alert(a+b);//
})();
//功能B
(function(){
var a = 2;
var b = 1;
alert(a-b);//
})();
[4]此时有了新需求,网页中加入功能C,且需要用到功能A中的变量b。于是在window作用域下定义一个全局变量,把它作为一个桥梁,完成各匿名函数之间的通信
//全局变量
var str;
//功能A
(function(){
var a = 1;
//将b的值赋给str
var b = str = 2;
alert(a+b);//
})();
//功能B
(function(){
var a = 2;
var b = 1;
alert(a-b);//
})();
//功能C
(function(){
//将str的值赋给b
var b = str;
alert(b);//
})();
[5]但如果功能C还需要功能A中的变量a呢,这时就需要再定义一个全局变量
//全局变量
var str,str1;
//功能A
(function(){
//将a的值赋给str1
var a = str1 = 1;
//将b的值赋给str
var b = str = 2;
alert(a+b);//
})();
//功能B
(function(){
var a = 2;
var b = 1;
alert(a-b);//
})();
//功能C
(function(){
//将str1的值赋给a
var a = str1;
//将str的值赋给b
var b = str;
alert(a*b);//
})();
[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);//
})();
//功能B
(function(){
var a = 2;
var b = 1;
alert(a-b);//
})();
//功能C
(function(){
//将GLOBAL.str1的值赋给a
var a = GLOBAL.str1;
//将GLOBAL.str的值赋给b
var b = GLOBAL.str;
alert(a*b);//
})();
[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);//
})();
//功能B
(function(){
//将a的值赋给GLOBAL.str1
var a = GLOBAL.str1 = 2;
var b = 1;
alert(a-b);//
})();
//功能C
(function(){
//将GLOBAL.str1的值赋给a
var a = GLOBAL.str1;
//将GLOBAL.str的值赋给b
var b = GLOBAL.str;
alert(a*b);//
})();
//功能D
(function(){
//将GLOBAL.str1的值赋给a
var a = GLOBAL.str1;
alert(a*2);//
})();
[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);//
})();
//功能B
(function(){
GLOBAL.B = {};
//将a的值赋给GLOBAL.B.str1
var a = GLOBAL.B.str1 = 2;
var b = 1;
alert(a-b);//
})();
//功能C
(function(){
//将GLOBAL.A.str1的值赋给a
var a = GLOBAL.A.str1;
//将GLOBAL.A.str的值赋给b
var b = GLOBAL.A.str;
alert(a*b);//
})();
//功能D
(function(){
//将GLOBAL.B.str1的值赋给a
var a = GLOBAL.B.str1;
alert(a*2);//
})();
[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);//
})();
//功能B
(function(){
var a = 2;
var b = 1;
GLOBAL.namespace('B');
GLOBAL.B.str1 = a;
alert(a-b);//
})();
//功能C
(function(){
var a = GLOBAL.A.str1;
var b = GLOBAL.A.str;
alert(a*b);//
})();
//功能D
(function(){
var a = GLOBAL.B.str1;
alert(a*2);//
})();
[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);//
})();
/*
* @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);//
})();
/*
* @method 功能C:实现乘法运算
* @author 工程师丙
* @connect 1234567
* @time 2015-01-01
*/
(function(){
var a = GLOBAL.A.str1;
var b = GLOBAL.A.str;
alert(a*b);//
})();
/*
* @method 功能D:实现乘2运算
* @author 工程师丁
* @connect 1234567
* @time 2015-01-01
*/
(function(){
var a = GLOBAL.B.str1;
alert(a*2);//
})();
让javascript不再冲突,需要
[1]避免全局变量的泛滥
[2]合理使用命名空间
[3]为代码添加必要的注释
如何避免javascript中的冲突的更多相关文章
- javascript中变量命名冲突的问题
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- JavaScript 中的数据类型
Javascript中的数据类型有以下几种情况: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Function,Date,Ar ...
- 深入理解JavaScript中创建对象模式的演变(原型)
深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...
- 浅谈JavaScript中的this
引言 JavaScript 是一种脚本语言,因此被很多人认为是简单易学的.然而情况恰恰相反,JavaScript 支持函数式编程.闭包.基于原型的继承等高级功能.本文仅采撷其中的一例:JavaScri ...
- JavaScript中的逗号运算符
JavaScript逗号运算符 阅读本文的前提,明确表达式.短语.运算符.运算数这几个概念. 所谓表达式,就是一个JavaScript的“短语”,JavaScript解释器可以计算它,从而生成一个值 ...
- 深入浅出 JavaScript 中的 this
在 Java 等面向对象的语言中,this 关键字的含义是明确且具体的,即指代当前对象.一般在编译期确定下来,或称为编译期绑定.而在 JavaScript 中,this 是动态绑定,或称为运行期绑定的 ...
- [转]Javascript中的自执行函数表达式
[转]Javascript中的自执行函数表达式 本文转载自:http://www.ghugo.com/javascript-auto-run-function/ 以下是正文: Posted on 20 ...
- 深入理解javascript中的立即执行函数(function(){…})()
投稿:junjie 字体:[增加 减小] 类型:转载 时间:2014-06-12 我要评论 这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是 ...
- 【转】深入浅出 JavaScript 中的 this
Java 等面向对象的语言中,this 关键字的含义是明确且具体的,即指代当前对象.一般在编译期确定下来,或称为编译期绑定.而在 JavaScript 中,this 是动态绑定,或称为运行期绑定的,这 ...
随机推荐
- select 取的是session里面的值时
原来是写了一个select标签,然后用js循环取出来,发现问题是本来嵌在页面右边的页面整个弹出来, 后来改成html:optionsCollection就好了: 效果图:
- [转载]iOS Provisioning Profile(Certificate)与Code Signing详解
原文:http://blog.csdn.net/phunxm/article/details/42685597 引言 关于开发证书配置(Certificates & Identifiers & ...
- C# Http Get 提交请求
/// <summary> /// HTTP GET方式请求数据. /// </summary> /// <param name="url">U ...
- vs2010中的MSBuild输出warning MSB8012问题
vs2010中,MSBuild与C++编译器无缝整合.无论使用vs2010生成的代码,还是转换vs2008或者是更低版本vs编译的C++代码.都会在工程编译后,都会提示一条错误: C:\Program ...
- linux指令之文件的创建、查询、修改
mkdir(make directory) 功能:创建目录 案例: mkdir test 点评:将创建一个目录名为test的目录 rmdir(remove directory) 功能:删除目录 案例: ...
- 设计模式之美:Object Pool(对象池)
索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):实现 DatabaseConnectionPool 类. 实现方式(二):使用对象构造方法和预分配方式实现 ObjectPool ...
- dijit样式定制(二)dijit.form.Select与dijit.form.NumberSpinner
dijit.form.Select: Select的样式位于Claro/form/Select.less中,Select主要通过table来布局,下图可以看到Select的布局结构 介绍几个主要的cl ...
- 团队项目——站立会议DAY14
第十四次站立会议记录: 参会人员:张靖颜,钟灵毓秀,何玥,赵莹,王梓萱 项目进展: 1.张靖颜:修改页面,查漏补缺.进行需求分析,监督每个组员,把大家的问题都一一梳理. 2.钟灵毓秀:继续修改模块代码 ...
- python--批量下载豆瓣图片
溜达豆瓣的时候,发现一些图片,懒得一个一个扒,之前写过c#和python版本的图片下载,因此拿之前的Python代码来改了改,折腾出一个豆瓣版本,方便各位使用 # -*- coding:utf8 -* ...
- Unity3D热更新全书-下载 唯一的一篇
下载在这个时代实在是太平常了,每个人都深刻的理解着下载到底是什么. 这一篇文字只是把下载的代码分享并介绍,而已. 首先,下载系统担负着几个使命. 第一.是保持客户端版本库的最新. 第二.是下载要能够比 ...