本文實例講解如何避免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 (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 })();
[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]為程式碼加上必要的註解
以上就是本文的詳細內容,希望對大家的學習有所幫助。
【相關教學推薦】