編寫可維護的js代碼
在工作中,制定一套統一的編碼風格,可以提高開發效率,維護起來的也要容易很多,也能避免一些不必要的錯誤出現。
項目中常用的檢查編碼風格的工具JSLint、JSHint、JSCS、ESLint,,在這呢,我就不介紹這些工具的使用,大家可以自行去看看官方文檔就好,我就給大家介紹平時寫時候的要點就好
基本的格式化
縮進層級
使用制表符進行縮進(tab鍵:一個制表符的長度相當於4個字符)
編輯器可以設置是一個縮進是2個空格還是4個空格還是8個空格,建議是使用4個空格,折中處理,很多編輯器默認也是4個空格.制表符和空格是兩個概念,不要混淆
語句結尾
語句結尾用分號結尾,如果省略了分號的話,JSLint和JSHint默認都會有警告 註意點:(javascript Standard標準裏面是可以不使用分號,加與不加就看你使用哪種標準)
// 合法的代碼
function sayHello(){
console.log(‘hello world‘)
}
// 合法的代碼
function sayHello(){
console.log(‘hello world‘);
}
行的長度
一行代碼不應該超過80個字符,超過80的話,就折行或隱藏
換行
當一行的長度達到了單行最大字符數限制是,就需要手動將一行拆成兩行,通常我們會在運算符後換行,下一行會增加兩個層級的縮進(兩個tab縮進)
callFunction(document,element,windiw,"some string value",true,123, navigation);
註意點:主體部分的話,還是保留一個層級的縮進(一個tab,4個字符) 例外:當個變量賦值時,第二行的位置應當和賦值運算符的位置保持對齊
var result=something + anotherthing + yetAnohterthing + somethingElse + anotherthingElse
空行
添加空行是為了提高代碼的可讀性,以下情況可以添加空行
- 在方法之間
- 在方法中的局部變量和第一條語句之間
if(flag){ for(let i=0;i<10;i++){ let p =i;
- 在多行或則單行註釋之前
- 在方法內的邏輯片段之間
未完待續....
下面場景中應當使用null
- 用來初始化一個變量,該變量可能為一個對象
- 用來和一個已經初始化的變量比較該變量可以使也可以不是一個對象
- 當函數的返回值期望是對象時,用作返回值傳出
下面場景不要用null
- 不要使用null來檢測是否傳入了某個參數
- 不要使用null來檢測一個未初始化的變量
代碼實例:
// 好的用法 var person=null; // 好的用法 function getPerson(){ if(condition){ return new Person("Nicholas"); } else{ return null } } // 好的用法 function getPerson(){ if(person!==null){ getMag(); } } // 不好的寫法:用來和初始化的變量比較 var person; if(person!==null){ getMag(); } // 不好寫法:檢測是否傳入了參數 function getArr(arg,agr2,agr3,agr4){ if(arg4!==null){ getMag(); } }
undefined
undefined不全等於null null==undefined // true null==undefined // false typeof undefined // "undefined" typeof null // object
註釋
單行註釋
- 獨占一行的註釋,用來解釋下一行代碼,折行註釋之前總是有一行空行,切且縮進層級和下一行代碼保持一致
- 在代碼的尾部的註釋,代碼結束到註釋之間要有至少一個縮進,註釋(包括之前的代碼部分)不應當超過單行最大字符數限制,如果超過了,就講這條註釋放置於當前代碼行額上方
- 被註釋掉的大段代碼可以用單行註釋,編輯器裏面有自帶
// 好的寫法:留有空行,及正確的縮進 if(condition){ // 代碼執行到這裏,則表明通過了所有的安全性檢查 allowed(); } // 不好的寫法:沒有空行及錯誤的縮進 if(condition){ // 代碼執行到這裏,則表明通過了所有的安全性檢查 allowed(); } // 好的寫法 var result=something +sometimes; // 是的就是這麽寫 // 不好的寫法: 代碼和註釋之間沒有間隔 var result=something +sometimes;// 是的就是這麽寫 // 好的寫法:代碼段使用單行註釋 // if(condition){ // flag=true; // allowed(); // } // 不好的寫法:這裏應該使用多行註釋 // 集體那第五次 // 集體那第五次 // 集體那第五次 // 集體那第五次 // 集體那第五次
多行註釋
建議的寫法是:
/* * 這是一段註釋,風格是仿Java的 */
- 多行註釋註釋和單行註釋一樣,前面都要留一行空行,且縮進層級和其描述的代碼保持一致
if(condition){ /* * 代碼執行到這裏,則表明通過了所有的安全性檢查 */ allowed(); }
文檔註釋
/** 這是一段說明文字 @method=merge @param {object} @return null **/
第三章:語句和表達式
所有的語句塊都應該使用花括號,包括:
- if
- for
- while
- do...while
- try..catch...finally
switch語句
縮進
switch (condition){ case "first": break; case "second": break; default: // 代碼 }
在JSLint中,是期望switch和case的層級縮進是一致的,如果不一致的話,就會警告,但是如果包含額外的空行的話,就不會報警告了
case語句的連續執行
可行方案:當你的代碼中出現了case的連續執行,JSLint就會給出警告,但是如果你加上了一句註釋的話,就能避免給出警告
switch (condition){ // 這裏的連續執行沒註釋,會給出警告 case "fisrt"; case "second": break; // 這裏不會給出警告 case "third": // 代碼 // fall through default: // 代碼 }
default
建議:當default中沒有邏輯代碼時,建議是可以省略default
for循環
盡量避免使用break,和continue語句
- break:退出循環
- continue:退出本次循環
for-in循環
for-in循環有個問題,就是它不僅遍歷對象的實例屬性,同樣還遍歷從原型繼承來的屬性,當遍歷自定義對象的屬性時,往往會因為意外的結果而終止,出於這個原因的考慮,最好使用hasOwnProperty()方法來為for-in循環過濾出實例屬性
for (item in obj){ if(obj.hasOwnProperty(item)){ console.log("Property is "+item); console.log("Property value is "+obj[item]); } }
對於循環沒有使用hasOwnProperty()方法的for-in循環,JSlint會給出警告
變量函數運算符
相等:在判斷相等的時候,為了規範,盡量用全等(=或則!)來判斷,目的是為了防止強制轉換
console.log(5==="5"); // true 把字符串轉為了數字來進行比較
原始包裝類型:
原始包裝類型有:String,Boolean,Number 3鐘類型,他們都具有對象的特征,但是在工作中不建議使用
var name="milk"; name.author="coat"; console.log(name.author); // undefined
註意點:原始值本身是不具有對象特征,比如1.toString();是報錯的必須這樣做:var a=1;a.toString();
UI層的松耦合
將css中JavaScript中抽離
在js裏面不應該直接操作樣式表,而應該是操作className
// 原生寫法 element.className+="reveal"; // h5中的寫法 element.ClassList.add("reveal");
將JavaScript從html中抽離
把JavaScript代碼寫到外部的js文件中,這樣的到時候修改就只需要修改一個文件就可以了
將html從JavaScript中抽離
從服務器加載
將模板放置在遠程服務器,使用XMLHttpRequest對象來獲取,但是該方法很容易造成XSS漏洞, 需要服務器對模板文件做適當的轉義處理
簡單的客戶端模板
// 這段中%s是占位符 var li=‘<li><a href="%s"></a></li>‘ var href="yes" function sprintf(text){ var i=1;args=arguments; return text.replace(/%s/g,function(){ return (i<args.length)?args[i++]:"" }) } console.log(sprintf(li,"nihao"));
通常做法:將模板定義在html標簽裏面,並且註釋掉模板文本,通過JavaScript的dom來提取
html部分: <ul id="mylist"> <!-- <li id="item%s"><a href="/item%s"></a></li> --> <li><a href="/item/2"></a></li> <li><a href="/item/3"></a></li> <li><a href="/item/4"></a></li> </ul> javascript部分: var mylist=document.getElementById("mylist"), templeText=mylist.childNodes[0].nextSibling.data; function sprintf(text){ let i=1,args=arguments; return text.replace(/%s/g,function(){ return (i<args.length) ? args[i++]:‘‘; }) } function addItem(url,text){ var mylist=document.getElementById("mylist"), templeText=mylist.childNodes[0].nextSibling.data || ""; console.log(templeText); result=sprintf(templeText,url,text); } // 這段中%s是占位符 var li=‘<li><a href="%s"></a></li>‘ // console.log(sprintf(li,"我也是","是啊是啊","我的")); addItem("/5","/five item");
檢測
檢測原始類型:
原始類型有:字符串,數字,布爾值,null,undefined
檢測原始類型最好的方式是用typeof運算符
· 檢測字符串 typeof 返回的是string
* 對於數字 返回的是 number
* 對於布爾值 返回的是布爾值
* 對於undefined 返回的是 undefined
* 對於null 返回的是 object
* NaN返回的是number
// 檢測字符串 if(typeof name==="string"){ return true; } // 檢測數字 if(typeof count==="number"){ return true; } // 檢測布爾值 if(typeof flag==="boolean" &&flag){ return true; } // 檢測undefined if(typeof myApp==="undefined"){ return true; }
檢測引用類型
內置的引用類型有:Array,Object,Date和Error
檢測最好是用instanceof來檢測:語法
value instanceof construtor
檢測的例子
// 檢測日期 if(value instanceof Date){ console.log(value) } // 檢測正則 if(value instanceof RegExp){ console.log(value) }
instance還可以檢測原型鏈
var now=new Date(); console.log(now instanceof Object); // true console.log(now instanceof Date); // true
檢測函數
函數檢測最好用typeof
function Fuc(){} console.log(typeof Fuc==="function"); // true
註意點:在IE8以及更早的版本中,typeof來檢測dom節點,的函數,返回的都是object而不是function(93頁中說明)
console.log(document.getElementById); //"object" console.log(document.getElement); //"object" console.log(document.getElementByTagName); //"object"
檢測數組
檢測數組的時候,用instanceof有時候並不一定準確,所以ES5中新增了一個isArray方法 說明:
var arr=[]; Array.isArray(arr); // true function isArray(value){ return Object.prototype.toString.call(value)==="[object Array]" } // 如果是json對象的話,返回的則是[object,JSON]
檢測屬性
- in 運算符檢測實例對象的某個屬性是否存在
var obj={ count:0, retlated:null } console.log("count" in obj);
- hasOwnProperty()方法 檢測實例對象的某個屬性是否存在:所有繼承自Object的javascript對象都有這個方法,如果實力中存在這個屬性則返回true(如果這個屬性只存在原型中,則返回false),需要註意的是,在IE8以及更早的IE版本中,dom並非繼承自Object,因此也不包含這個方法,,也就是說你在調用dom對象的hasOwnProperty()方法之前,應當檢測其是否存在
-
-
// 對於所有非dom對象來說, 這是好的寫法 if (object.hasOwnProperty(‘related‘)){ // 執行這裏的代碼 } // 如果你不確定是否為dom對象,則這樣寫 if("hasOwnProperty" in Object&&object.hasOwnProperty(‘relative‘)){ // 執行這裏的代碼 }
-
-
編寫可維護的js代碼