實例講解避免javascript沖突的方法
本文實例講解了如何避免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,產(chǎn)生沖突。于是使用匿名函數(shù)將腳本包起來,讓變量作用域控制在匿名函數(shù)之內(nèi)。
//功能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]此時有了新需求,網(wǎng)頁中加入功能C,且需要用到功能A中的變量b。于是在window作用域下定義一個全局變量,把它作為一個橋梁,完成各匿名函數(shù)之間的通信
//全局變量
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
})();
[6]但隨著匿名函數(shù)之間需要通信的變量越多,需要的全局變量也就越多。因此需要嚴(yán)格控制全局變量的數(shù)量,使用hash對象作為全局變量,可以將需要的變量都作為對象的屬性,可以保證全局變量的個數(shù)足夠少,同時拓展性非常好
//全局變量
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,開發(fā)功能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]由于工程師丁只關(guān)心自己的匿名函數(shù)和功能B的匿名函數(shù),使用GLOBAL.str卻無意中覆蓋了功能A中設(shè)置的同名變量,導(dǎo)致功能C出錯。于是使用命名空間來解決這個問題,在不同的匿名函數(shù)下,根據(jù)功能聲明一個不同的命名空間,然后每個匿名函數(shù)中的GLOBAL對象的屬性都不要直接掛在GLOBAL對象上,而是掛在此匿名函數(shù)的命名空間下
//全局變量
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]如果同一個匿名函數(shù)中的程序非常復(fù)雜,變量名很多,命名空間還可以進一步拓展,生成二級命名空間
//以功能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]因為生成命名空間是個非常常用的功能,進一步將生成命名空間的功能定義成一個函數(shù),方便調(diào)用,完整版本改寫后的代碼如下
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]代碼的沖突問題已經(jīng)解決了,但可維護性并不強。比如,現(xiàn)在需要讓工程師甲去修改功能B。因為工程師甲寫的腳本是關(guān)于功能A的,他并不知道功能B的腳本情況。為了改善這種局面,需要給代碼添加適當(dāng)?shù)淖⑨尅?/p>
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:實現(xiàn)加法運算
* @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:實現(xiàn)減法運算
* @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:實現(xiàn)乘法運算
* @author 工程師丙
* @connect 1234567
* @time 2015-01-01
*/
(function(){
var a = GLOBAL.A.str1;
var b = GLOBAL.A.str;
alert(a*b);//2
})();
/*
* @method 功能D:實現(xiàn)乘2運算
* @author 工程師丁
* @connect 1234567
* @time 2015-01-01
*/
(function(){
var a = GLOBAL.B.str1;
alert(a*2);//4
})();
讓javascript不再沖突,需要
- [1]避免全局變量的泛濫
- [2]合理使用命名空間
- [3]為代碼添加必要的注釋
以上就是本文的詳細(xì)內(nèi)容,希望對大家的學(xué)習(xí)有所幫助。
相關(guān)文章
javascript實現(xiàn)在下拉列表中顯示多級樹形菜單的方法
關(guān)于Javascript中值得學(xué)習(xí)的特性總結(jié)
根據(jù)鼠標(biāo)的位置動態(tài)的控制層的位置

