為什么要編寫可維護的javascript?
軟件生命周期80%的成本消耗在了維護上。
幾乎所有的軟件維護者都不是它的最初作者。
編碼規(guī)范提高了軟件的可讀性,它讓工程師能夠快速且充分地理解新的代碼。
程序是寫給人讀的,只是偶爾讓計算機執(zhí)行以下。 ——高德納
如何處理縮進是幾乎所有語言首先討論的,縮進甚至關(guān)系到軟件工程師的價值觀!
第一種縮進:使用制表符進行縮進。例如:jQuery核心風(fēng)格,Dojo編程風(fēng)格。
第二種縮進:使用空格符進行縮進。例如:Goolge的javascript規(guī)定使用兩個空格縮進。
推薦:4個空格字符為一個縮進層級,可以在編輯器中配置Tab鍵插入4個空格。
你加沒加分號代碼可能都會正常運行,沒看到這里之前,你可能不知道這是分析器的自動分號插入機制(ASI)在偷偷的幫你干活。常言道:常在河邊走,哪有不濕鞋?看看下面的代碼。
function getData() { return { text: '看看不加分號的后果!' } }ASI會解析成下面的樣子:function getData() { return ; { text: '看看不加分號的后果!' }; }
所以如果調(diào)用上面的getData的方法,返回的就是undefined。但是這樣不能全怪分號,誰讓你把花括號寫到下面一行的?(反正我看到有第一個花括號跟之前的語句不在一行的,我就要暴走。)
//這段代碼工作正常,盡管沒有分號function getData() { return { text: '看看不加分號的后果!' } }
如果一行多于80個字符,應(yīng)當(dāng)在一個運算符(逗號,加號等)后換行。下一行應(yīng)當(dāng)增加兩級縮進。
計算機科學(xué)只存在兩個難題:緩存失效和命名。
ECMAScript遵照了小駝峰的命名法,所謂小駝峰,官方稱之為“駝峰大小寫命名法(Camel Case)”,是由小寫字母開始的,后續(xù)每個單詞首字母都大寫。
//例如var thisIsMyName;
變量命名前綴應(yīng)該是名詞。函數(shù)名前綴應(yīng)該是動詞。
//變量var myName = 'chen';//函數(shù)名function getName() { return myName;}
在ECMAScript6之前,javascript中沒有真正的常量概念。根據(jù)C語言的樣子,約定使用大寫字母和下劃線來命名,下劃線用以分割單詞。
var MAX_COUNT = 10;//現(xiàn)在我們應(yīng)該也可以這樣定義常量const MAX_COUNT = 10;
構(gòu)造函數(shù)的命名遵照大駝峰命名法(Pascal Case),為什么?因為跟本地語言保持一致的命名約定,new RegExp()
,正則本身就是一個內(nèi)置的構(gòu)造函數(shù),看見大駝峰了木有?
科普一下:Pascal Case 和 Camel Case都表示“駝峰大小寫”,區(qū)別在于:
Pascal Case是以大寫字母開始,所以也叫大駝峰,例如:AnotherName;
Camel Case是以小寫字母開始,之后的單詞首字母大寫,所以也叫小駝峰,例如:anotherName,之前在命名的那塊提到過小駝峰。
直接量可以這么理解,它是程序中可以直接使用的數(shù)據(jù),沒有進行特別的封裝。
2 //數(shù)字直接量"其心" //字符串直接量[1,2,3] //數(shù)組直接量true //布爾型直接量{name: "其心"} //對象直接量(function(){})() //函數(shù)直接量/*分割線*/new String("其心") //這就不是直接量
在直接量里著重說一下null
,我就經(jīng)常誤解它,用的很隨意,現(xiàn)在我明確了解了,應(yīng)該在下列場景中使用它。
用來初始化一個變量,這個變量可能賦值給一個對象。
用來和一個已經(jīng)初始化的變量比較,這個變量可以是也可以不是一個對象。
當(dāng)函數(shù)的參數(shù)期望是對象時,用作參數(shù)出入。
當(dāng)函數(shù)的返回值期望是對象時,用作返回值傳出。
理解null最好的方式是讓他們當(dāng)做對象的占位符。
直接量的用法簡潔高效,是值得提倡的,這一點謹(jǐn)記。
單行注釋有三種使用方法:
獨占一行的注釋,用來解釋下一行代碼。這行注釋之前總要有一個空行,且縮進層級和下一行代碼保持一致。
// 好的寫法function print(){ // 控制臺輸出數(shù)字1 console.log(1);}
在代碼行的尾部的注釋。代碼結(jié)束到注釋之間至少有一個縮進。注釋(包括之前代碼部分)不應(yīng)當(dāng)超過單行最大字符數(shù)限制,如果超過了,就講這條注釋放置于當(dāng)前代碼的上方。
被注釋掉的打斷代碼。
//好的寫法// function print(){// console.log(1);// }
比較青睞Java風(fēng)格的多行注釋
/**這是一段注釋*這段注釋包含兩行文本*/
多行注釋之前也應(yīng)該有一個空行,且縮進層級和其描述的代碼保持一致。
多提一點就是文檔的注釋,多行注釋以單斜線加雙星號(/**)開始,接下來是描述信息,其中使用@符號來表示一個或多個屬性。
/** * 提交JSON數(shù)據(jù) * @param actionUrl 交互的URL * @param json JSON數(shù)據(jù) * @param postSuccessFn 提交成功的回調(diào)函數(shù) * @param postFailFn 提交失敗的方法 * @param isAsync 是否異步提交,true:是 * @param timeout 請求時限 */
首先說一點,見到下面兩種寫法,都是合法的JavaScript的代碼,但是不提倡使用。
// 不好的寫法if(condition) doSomething();// 不好的寫法if(condition) doSomething();
第一種風(fēng)格是,將左花括號放置在塊語句中第一句代碼的末尾。這種風(fēng)格繼承自Java。
if (condition) { doSomething(); }else { doSomethingElse(); }
第二種風(fēng)格是,將花括號放置于塊語句首行的下一行。這是隨著C#流行起來的。
if (condition) { doSomething(); }else { doSomethingElse(); }
為了避免導(dǎo)致錯誤的分號自動插入(還記得之前說過的“ASI”么),推薦使用第一種花括號對齊方式。
對于switch的縮進之類可以直接用編輯器默認(rèn)的,只提一點就是,如果程序沒有默認(rèn)的行為時,default是可以被省略的。
1、變量
建議將局部變量的定義作為函數(shù)內(nèi)第一條語句,推薦使用單個var語句,每個變量的初始化獨占一行。對于沒有初始化的變量來說,它們應(yīng)當(dāng)出現(xiàn)在var語句的尾部。
function doSomething(items) { var value = 10, result = value 10, i, len; for(i = 0,len = items.length; i < len; i ){ doOtherSomething(items[i]); }}
需要注意,函數(shù)聲明應(yīng)當(dāng)在條件語句的外部使用。例如:
//不好的寫法,大部分瀏覽器會自動使用第二個聲明,并不會根據(jù)condition來做判斷。if (condition) { function doSomething() { alert("Hi!"); } } else { function doSomething() { alert("Yo!"); } }
JavaScript具有強制類型轉(zhuǎn)換的機制。
數(shù)字和字符串比較,字符串會首先轉(zhuǎn)換為數(shù)字,然后執(zhí)行比較。
// 比較數(shù)字5和字符串5console.log(5 == "5"); // true// 比較數(shù)字25和十六進制的字符串25console.log(25 == "0x19"); // true
一個布爾值和數(shù)字比較,布爾值會首先轉(zhuǎn)化為數(shù)字,然后進行比較,false是0,true是1。
// 比較數(shù)字1和trueconsole.log(1 == true); // true// 比較數(shù)字0和falseconsole.log(0== false); // true//比較數(shù)字2和trueconsole.log(2 == true); // false
比較一個值是對象而另一個不是,會首先調(diào)用對象的valueOf()方法得到原始類型在進行比較。如果沒有定義valueOf(),則調(diào)用toString()。
由于強制類型轉(zhuǎn)換的緣故,推薦用===或者!==,不應(yīng)當(dāng)使用==或者!=
JavaScript有5中簡單的原始類型:字符串、數(shù)字、布爾值、null和undefined。最佳的選擇是用typeof運算符,返回一個值的類型的字符串。
用typeof檢測一下4種原始值類型是非常安全的。
//檢測字符串if (typeof name === "string") { anotherName = name.substring(3);}//檢測數(shù)字if (typeof count === "number") { updateCount(count);}//檢測布爾值if (typeof found === "boolean" && found){ message("Found!");}//檢測underfinedif (typeof MyApp=== "undefined") { MyApp = {};}
引用值也稱為對象,檢測某個引用值的類型的官方最好的方法是使用instanceof運算符。但是它不僅檢測構(gòu)造這個對象的構(gòu)造器,還檢測原型鏈。因為每個對象都繼承自O(shè)bject,因此每個對象的 value instanceof Object
都會返回true。
var now = new Date();console.log(now instanceof object); // trueconsole.log(now instanceof Date) // true
最開始是判斷sort()方法在不在。
function isArray(value) { return typeof value.sort === "function";}
然后有了一種比較優(yōu)雅的解決方案。
function isArray() { return Object.prototype.toString.call(value) === "[object Array]";}
再后來ECMAScript5將Array.isArray()正式引入JavaScript。
判斷屬性是否存在的最好的方法是使用in運算符。in運算符只會簡單地判斷屬性是否存在,而不會去讀屬性的值。但是檢測出來的屬性可以是對象自身的,也可以是繼承來的。
var object = { count: 0, related: null};if ("count" in object) { //這里的代碼會執(zhí)行}
如果只檢查對象自身的某個屬性是否存在,就使用hasOwnProperty()方法。
配置數(shù)據(jù)類似:
URL
需要展現(xiàn)給用戶的字符串
重復(fù)的值
設(shè)置(比如每頁的配置項)
任何可能發(fā)生變更的值
類似于各種工具化文件的config。
Error: 所有的錯誤類型。實際上引擎從來不會拋出該類型的錯誤。
EvalError: 通過eval()函數(shù)執(zhí)行代碼發(fā)生錯誤時拋出。
RangeError: 一個數(shù)字超出它的邊界時拋出。
ReferenceError: 期望的對象不存在時拋出。
SyntaxError: 給eval()函數(shù)傳遞的代碼中有語法錯誤時拋出。
TypeError: 變量不是期望的類型時拋出。
防止擴展
禁止為對象“添加”屬性和方法,但已存在的屬性和方法是可以被修改或刪除。
Object.preventExtension(); // 鎖定對象Object.isExtensible(); // 判斷對象是否被鎖定
密封
類似“防止擴展”,而且禁止為對象“刪除”已存在的屬性和方法。
Object.seal(); // 密封對象Object.isSealed(); // 檢測一個對象是否已被密封
凍結(jié)
類似“密封”,而且禁止為對象“刪除”已存在的屬性和方法。
Object.freeze(); // 凍結(jié)對象Object.isFrozen(); // 判斷一個對象是否已被凍結(jié)
來源:https://www.icode9.com/content-1-665601.html