也談談規范JS代碼的幾個注意點
寫JS代碼差不多也有兩年了吧,從剛開始的“初生牛犢不怕虎”亂寫一通到后來也慢慢知道去規范一下自己寫的代碼。這種感覺就像是代碼是你的作品,你希望它保持一份不僅干凈而且也優雅的姿勢。所以后來慢慢規范了自己寫的代碼,再后來覺得僅僅規范自己的代碼還不行,這個團隊其他人的也需要保持一致,再再后來就開始嘗試寫了一份代碼規范,用於規范團隊的代碼質量。網上有不少講代碼規范的書,我也就不再獻丑了,大家可以去看看阿里\百度\騰訊他們的代碼規范,寫的非常不錯。我就僅僅把自己遇到的嘗試做一下總結,這些可能別人也總結過無數次了,歡迎吐槽交流,也希望對你有點兒幫助。
1、減少全局污染
我們都知道javascript使用function來管理自己的作用域,一個定義在函數內的變量對外是不可見的,這有點類似於其它語言里的私有變量。對於javascript的執行環境來說一般都有一個全局變量,在所有的函數外可以用this來指引,例如在瀏覽器端是window。但是當過多的在全局執行環境下定義變量會造成各種苦逼的事情,比方說你定義的變量被其他人定義的同名變量覆蓋掉,或者你未來定義的變量把你過去定義的同名變量也覆蓋掉,而且過多的全局變量放在執行對戰里還會造成內存的浪費等等不優化的情況發生。我就不再具體講沒個苦逼的事情是如何苦逼了,僅僅講講可能會導致這種情況發生的不好的示例吧。
①聲明變量忘記使用“var”的情況。
1 var sample = function () { 2 var a1 = "hello"; 3 a2 = "world"; 4 }; 5 sample(); 6 alert(a1);//undefined 7 alert(a2);//world
如你所見,a2因為忘記使用var導致了它成為了全局的變量,這樣就有可能造成其它地方的修改覆蓋它或者將其它地方的變量覆蓋等(忘記var也會使得該變量可以delete)。正確的做法是,所有的變量都使用“var”,並且盡量都生命在函數體的頭部,這樣一目了然。如下:
1 var sample = function () { 2 var a1 = true,//標識位1 3 a2 = true, //標識位2 4 a3 = false;//標識位3 5 6 //do some logic 7 8 };
(注:用“,”號隔開變量可以避免過多使用"var"。)
②變量名提升。
javascript中函數內所有使用var聲明的變量都會提升到函數體頭部,這也是很多人容易犯錯的一點。具體來講就是:
1 myname = "global"; 2 function sample() { 3 alert(myname); // "undefined" 4 var myname = "local"; 5 alert(myname); // "local" 6 } 7 sample();
如你所見,第一個alert出來的並非global。原因在於,函數sample內部聲明的myname會提升到函數體頂部,而原語句的地方才是正在賦值的地方。在聲明和賦值直接引用的話肯定是undefined了。其執行效果如下:
1 myname = "global"; 2 function sample() { 3 var myname;//沒有賦值 4 alert(myname); // "undefined" 5 myname = "local";//此處賦值 6 alert(myname); // "local" 7 } 8 sample();
所以一個重要的經驗就是,在函數體講所有的var聲明的東西都拿到函數體頂部,以免造成不必要的錯誤。
2、for循環。
我們習慣將for循環寫成如下形式:
1 for (var i = 0; i < myarray.length; i++) { 2 //logic 3 }
看似沒有問題,但是如果myarray是讀取的DOM的節點,那么每一次循環都要去DOM里選取節點再做判斷,非常影響性能。可能數量不大感覺不錯來,多了就非常嚴重了。所以,for循環判斷條件里盡量不要使用涉及到DOM操作的動作。優化如下:
1 for (var i = 0, max = myarray.length; i < max; i++) { 2 // logic 3 }
另外一個就是使用for-in循環對象的話會讀取對象從原型鏈里的屬性,如果這不是希望的,那么可以用一個判斷hasOwnProperty(i)去掉它。
3、用“===”取代“==”
前者是嚴格判斷,后者會提前進行隱式的類型轉換。
4、不使用eval()
5、統一縮進大小(無論用tab或者2個或者4個空格,團隊統一即可),任何用花括號括起來並換行的都進行縮進。
6、花括號{}
for循環或者if判斷等,即使只有一行,也要換行並用{}括起來。
7、空格
任何“;”后空一格、for循環中初始化“,”后空一格、數組中","后空一格、對象中“:”后空一格、如:
1 for (var i = 0, j = 1; i < 10; i += 1){
2 var some = [1, 2, 3];
3 var obj = {aa: 1, bb: 2}
3 }
函數參數里“,”后空一格、函數聲明中花括號前空一格、函數表達式中括號前后各空一格,如:
1 func(a, b, c){}; 2 function func() {}; 3 var func = function () {};
所有的操作符前后都跟一個空格,如:
1 var d = 0, 2 a = b + 1; 3 if (a && b && c) { 4 d = a % c; 5 a += d; 6 }
8、命名規則
構造器函數首字母大寫,如:
1 function Person() {...}
變量用駝峰式,如:
1 getFirstName()
常量全用大寫字母,如:
1 var PI = 3.1415926;
私有函數用下划線開頭,如:
1 var person = { 2 _setSext: function () { 3 // ... 4 }, 5 _setName: function () { 6 // ... 7 } 8 };
9、寫注釋
這一步非常關鍵,因為你寫的代碼別人不一定看得懂,你寫的將來你也不一定輕易能看懂。所以良好的注釋習慣可以事半功倍。
感謝你這么大的耐性,天馬行空的對着自己寫的代碼總結了一點兒,希望多少對你有點啟發。