前言: 雖然最近項目週期挺緊張的,晚上仍是儘可能擠出時間閱讀《編寫可維護的JavaScript》這本書籍。書籍總共分爲三部分(編程風格,編程實踐,自動化),本文是第一部分編程風格中我認爲比較精彩的片斷(檢測值 && 格式化),也應用在了當前的項目中,整理出來跟你們分享,但願對你們在重構優化代碼方面可以帶來必定的幫助。前端
在JavaScript中,咱們經常會看到這種代碼:變量和null的比較(這種寫法頗有問題),用來判斷變量是否賦被賦予了一個合理的值。好比:正則表達式
var Controller = {
process: function (items) {
if (item !== null) { // 很差的寫法
items.sort()
items.forEach(item => {
// 一些代碼
})
}
}
}
複製代碼
在這段代碼中,process方法顯然是但願items是一個數組,由於咱們看到items擁有sort()和forEach().這段代碼的意圖很是明顯;若是參數items不是一個數組,則中止接下來的操做。咱們來分析一下,這種寫法的問題在於和null比較並不能真正避免錯誤的發生。items的值能夠是1,也能夠是字符串,甚至能夠是任意對象。這些值都和null不相等,進而會致使process()方法一旦執行到sort()時就會出錯。編程
僅僅和null比較並不能提供足夠的信息來判斷後續的代碼執行是否真的安全。好在JavaScript爲咱們提供了多種方法來檢測變量的真實值。數組
在JavaScript中有5種原始類型:字符串,數字,布爾值,undefined,null安全
對於字符串,數字,布爾值,undefined,最佳選擇是使用typeof運算符微信
示例代碼:函數
// 檢測字符串
if (typeof name === "string") {
// 執行代碼
}
// 檢測數字
if (typeof count === "number") {
// 一些代碼
}
// 檢測數字
if (typeof found === "boolean") {
// 一些代碼
}
// 檢測undefined
if (typeof MyApp === "undefined") {
// 一些代碼
}
複製代碼
對於null工具
null,通常不該用於檢測語句。正如上文情景引入中提到的,簡單地和null比較一般不會包含足夠的信息以判斷值的類型是否合法。但有一個例外,若是所指望的值真的是null,則能夠直接和null進行比較。 若是使用typeof運算符比較null,運行typeof null則返回'object',這是一種低效的判斷null的方法。 若是你須要驗證null,請直接使用恆等運算符(===)或非等運算符(!==) 示例代碼: 輸入框的值的判斷優化
if (this.skuName !== null) {
// 輸入框有值才執行請求接口
this.copySkuBlock()
} else {
// 提示輸入框要輸入值
this.$message({
type: 'error',
message: '請輸入商品規格'
})
}
複製代碼
在JavaScript鐘有4種引用類型:Object, Array, Date, 和Error。ui
示例代碼:
// 檢測日期
if (value instanceof Date) {
// 一些代碼
}
// 檢測正則表達式
if (value instanceof RegExp) {
// 一些代碼
}
// 檢測Error
if (value instanceof Error) {
// 一些代碼
throw value
}
複製代碼
從技術上講, JavaScript中的函數是引用類型,一樣存在Function構造函數。因爲instanceof運算符不能跨幀使用,typeof運算符則是檢測函數的最佳選擇。
示例代碼:
function myFunc () {
// 很差的寫法 不能跨幀使用,由於每一個幀都有各自的Function構造函數
console.log(myFunc instanceof Function) // true
// 好的寫法 能跨幀使用, 但只能在IE9+使用
console.log(typeof myFunc === "function") // true
}
複製代碼
ES5將**Array.isArray()**的方法正式引入JavaScript,惟一的目的就是準確地檢測一個值是否爲數組,IE9+支持。
示例代碼:
function isArray () {
if (typeof Array.isArray === "function") {
return Array.isArray(value)
} else {
return Object.prototype.toString.call(value) === "[object Array]"
}
}
複製代碼
另一種用到null(以及undefined)的場景是當檢測一個屬性是否在對象中存在時。好比:
// 很差的寫法: 和null比較
if (object[propertyName] !== null) {
// 一些代碼
}
複製代碼
判斷對象中的屬性是否存在最好的方法是使用in運算符。 in運算符僅僅會簡單地判斷屬性是否存在,而不會去讀屬性的值。
示例代碼:
A. 若是實例對象的屬性存在、或者繼承自對象的原型,in運算符都會返回true。好比:
if ("count" in object) {
// 一些代碼
}
複製代碼
B. 若是你只想檢測實例對象的某個屬性是否存在,則使用hasOwnProperty()方法,僅支持IE9+
if (object.hasOwnproperty("count")) {
// 一些代碼
}
複製代碼
所以,在判斷實例對象的屬性是否存在時,我更傾向於使用in運算符,只有在須要判斷實例屬性時纔會用到hasOwnproperty,這樣作能夠避免不少bug。
1.變量和函數, 都用小駝峯式命名,變量用名詞做前綴,函數用動詞做前綴。
2.禁止使用特殊值underfined,能夠有效地確保只在一種狀況下typeof纔會返回「underfined」
1.使用註釋的原則 當代碼不夠清晰時添加註釋,而當代碼很明瞭時不該當添加註釋當代碼不夠清晰時添加註釋,而當代碼很明瞭時不該當添加註釋
2.文檔註釋 開源項目中,強烈推薦用文檔生成工具來生成文檔註釋,好比YUIDoc或JSDoc Toolkit。 在Google內部的不少開源項目JSDoc Toolkit的應用很是普遍,這二者的區別在於,YUIDoc能夠同時支持文檔註釋中的HTML和Markdown格式,而JSDoc Toolkit 只支持HTML
1.for循環
儘可能用條件語句代替for循環中的continue,更加容易理解且不容易出錯
示例代碼
// 很差的寫法
var values = [0, 1, 2, 3, 4, 5, 6],
i,len
for (i = 0, len = values.length; i < len; i++) {
if (i === 2 ) {
// 跳過本次循環
continue
}
console.log('第' + i + '次循環')
}
// 好的寫法
var values = [0, 1, 2, 3, 4, 5, 6],
i,len
for (i = 0, len = values.length; i < len; i++) {
if (i !== 2 ) {
console.log('第' + i + '次循環')
}
}
複製代碼
2.for-in循環
for-in不只遍歷對象的實例屬性,一樣還會遍歷從原型繼承來的屬性。所以,當遍歷自定義對象的屬性時,for-in遍歷對象會遍歷從原型繼承來的屬性,建議使用hasOwnProperty()方法來爲for-in循環過濾出實例的屬性
示例代碼
// 好的寫法
var prop
for (prop in object) {
if (object.hasOwnProperty(prop)) {
console.log('Property name is' + prop)
console.log('Property value is' + object[prop])
}
}
複製代碼
我推薦老是在for-in循環中使用hasOwnProperty(), 除非你想查找原型鏈,這時應當補充註釋,好比:
// 好的寫法
var prop
for (prop in object) { // 包含對原型鏈的遍歷
console.log('Property name is' + prop)
console.log('Property value is' + object[prop])
}
複製代碼
for-in循環是用來遍歷對象的,禁止用來遍歷數數組成員
示例代碼
// 很差的寫法
var values = [1, 2, 3],
i
for (i in values) {
console.log('Property name is' + i) // 0, 1, 2
console.log('Property value is' + values[i]) // 1, 2, 3
}
複製代碼
1.變量聲明
將局部變量的定義做爲函數內第一條語句;全部的var語句合併爲一個語句,每一個變量的初始化獨佔一行。賦值運算符應當對齊。對於那些沒有初始值的變量來講,它們應當出如今var語句的尾部。
示例代碼
// 好的寫法
function doSomething () {
// 局部遍歷的定義
var value = 10,
result = value + 10,
i,
len
for (i = 0, len = items.length; i < len; i++) {
doOtherSomething(items[i])
}
}
複製代碼
use strict 不只適用於全局,也適用於局部,可是最好不要在全局做用域中使用「use strict」模式
示例代碼
// 很差的寫法 全局的嚴格模式
'use strict'
function doSomething () {
// 一些代碼
}
// 好的寫法
(function () {
'use strict'
function doSomething () {
// 一些代碼
}
function doSomethingElse () {
// 一些代碼
}
})
複製代碼
3.運算符
因爲JavaScript具備強制類型轉換機制的緣故,咱們推薦不要使用==和!=,而是應當使用===和!==.
示例代碼
// 很差的寫法 字符串會被轉爲數字,而後再進行比較
console.log(5 == '5') // true
// 好的寫法
console.log(5 === '5') // false
複製代碼
4.函數
eval()
通用原則:嚴禁使用function,而且只在別無他法時使用eval()
that's all, 以上就是我目前全部的對第一部分編程風格的理解以及應用。以爲對你開發有幫助的能夠點贊收藏一波,若是我哪裏寫錯了,但願能指點出來。若是你有更好的想法或者建議,能夠提出來在下方評論區與我交流。你們一塊兒進步,共同成長。感謝[鞠躬]。
我的的微信公衆號,付出的前端路,訂閱微信公衆號yhzg_gz(點擊複製,在微信中添加公衆號粘貼便可)
ps: 提升本身,常與異性交朋友