Airbnb規(guī)范

  • 不使用分號(hào)
  • 使用分號(hào)

為什么? 當(dāng) JavaScript 遇到?jīng)]有分號(hào)的換行符時(shí)施籍,它使用一組稱(chēng)為自動(dòng)分號(hào)插入的規(guī)則來(lái)確定是否應(yīng)該將換行符視為語(yǔ)句的結(jié)尾,并且(顧名思義)如果被這樣認(rèn)為的話,在換行符前面自動(dòng)插入一個(gè)分號(hào)。ASI(自動(dòng)分號(hào)插入)包含了一些稀奇古怪的的行為承边,不過(guò),如果 JavaScript 錯(cuò)誤地解釋了你的換行符石挂,你的代碼將會(huì)被中斷執(zhí)行。隨著新功能成為 JavaScript 的一部分险污,這些規(guī)則將變得更加復(fù)雜痹愚。明確地結(jié)束你的語(yǔ)句并配置你的 linter 來(lái)捕獲缺少的分號(hào),將有助于防止遇到問(wèn)題

  • 不使用逗號(hào)結(jié)尾

  • 使用逗號(hào)結(jié)尾

  • 使用let蛔糯,const拯腮,摒棄var

const a = [1, 2], const b = a, b[0] = 9, a = ?, b = ?
  • 使用字面量創(chuàng)建Object和Array
// bad
const obj = new Object(), const arr = new Array()

// good
const obj = {1, 2, 3}, const arr = [7, 8, 9]
  • {}前后要空格
 { 1, 2, 3 }
  • []前后無(wú)需空格
[1, 2, 3]
  • 注釋符號(hào)后面要空格
// 注釋
  • 逗號(hào)之后要空格
const a = [1, 2, 3]
  • 冒號(hào)之后要空格
const obj = { abc: 123 }
  • 使用對(duì)象方法速記語(yǔ)法
// bad
const atom = {
    value: 1,
 
    addValue: function (value) {
    return atom.value + value;
    },
}

// good
const atom = {
    value: 1,
 
    addValue(value) {
    return atom.value + value;
    },
}
  • 使用表達(dá)式創(chuàng)建funtion
// 為什么? 函數(shù)聲明很容易被提升(Hoisting)蚁飒,你可以在函數(shù)被定義之前引用該函數(shù)动壤。這對(duì)可讀性和可維護(hù)性來(lái)說(shuō)都是不利的。

// bad
function fn () {}

// good
const fn = () => {}
  • 使用對(duì)象屬性速記語(yǔ)法
// bad
const obj = { abc: abc }

// good
const obj = { abc }
  • 只用引號(hào)引無(wú)效標(biāo)識(shí)符的屬性
// bad
const bad = {
    'foo': 3,
    'bar': 4,
    'data-blah': 5,
}

// good
const good = {
    foo: 3,
    bar: 4,
    'data-blah': 5,
}
  • 使用展開(kāi)符…復(fù)制數(shù)組
// bad
const len = items.length
const itemsCopy = []
let i
 
for (i = 0; i < len; i += 1) {
    itemsCopy[i] = items[i]
}
 
// good
const itemsCopy = [...items]
  • 使用展開(kāi)操作符 ... 代替 Array.from
const foo = document.querySelectorAll('.foo');
 
// good
const nodes = Array.from(foo);
 
// best
const nodes = [...foo];
  • 在數(shù)組方法回調(diào)中使用 return 語(yǔ)句淮逻。如果函數(shù)體由一個(gè)返回?zé)o副作用的表達(dá)式的單個(gè)語(yǔ)句組成琼懊,那么可以省略返回值
// bad
inbox.filter((msg) => {
    const { subject, author } = msg;
    if (subject === 'Mockingbird') {
    return author === 'Harper Lee'
    } else {
    return false
    }
})
 
// good
inbox.filter((msg) => {
    const { subject, author } = msg;
    if (subject === 'Mockingbird') {
    return author === 'Harper Lee'
    }
 
    return false
})
  • 當(dāng)訪問(wèn)和使用對(duì)象的多個(gè)屬性時(shí),請(qǐng)使用對(duì)象解構(gòu)
// bad
function getFullName(user) {
    const firstName = user.firstName
    const lastName = user.lastName
 
    return `${firstName} ${lastName}`
}
 
// good
function getFullName(user) {
    const { firstName, lastName } = user
    return `${firstName} ${lastName}`
}
 
// best
function getFullName({ firstName, lastName }) {
    return `${firstName} ${lastName}`
}
  • 使用數(shù)組解構(gòu)
const arr = [1, 2, 3, 4]
 
// bad
const first = arr[0]
const second = arr[1]
 
// good
const [first, second] = arr
  • 字符串使用單引號(hào) ''
// bad
const name = "Capt. Janeway"
 
// bad - 模板字面量應(yīng)該包含插值或換行符
const name = `Capt. Janeway`
 
// good
const name = 'Capt. Janeway'
  • 以編程方式構(gòu)建字符串時(shí)爬早,請(qǐng)使用模板字符串而不是字符串連接
// bad
function sayHi(name) {
    return 'How are you, ' + name + '?'
}
 
// bad
function sayHi(name) {
    return ['How are you, ', name, '?'].join()
}
 
// bad
function sayHi(name) {
    return `How are you, ${ name }?`
}
 
// good
function sayHi(name) {
    return `How are you, ${name}?`
}
  • 不要使用 arguments哼丈,可以選擇 rest 語(yǔ)法 ... 替代
//為什么?使用 ... 能明確你要傳入的參數(shù)筛严。另外 rest(剩余)參數(shù)是一個(gè)真正的數(shù)組醉旦,而 arguments 是一個(gè)類(lèi)數(shù)組(Array-like)。

// bad
function concatenateAll() {
    const args = Array.prototype.slice.call(arguments);
    return args.join('');
}
 
// good
function concatenateAll(...args) {
    return args.join('');
}
  • 使用默認(rèn)參數(shù)語(yǔ)法,而不要使用一個(gè)變化的函數(shù)參數(shù)
// bad
function handleThings(opts) {
    opts = opts || {};
      // 如果opts的值就是false怎么辦车胡?按上面的寫(xiě)法檬输,它永遠(yuǎn)等于{}了,也就是true
    // ...
}
 
// good
function handleThings(opts = {}) {
    // ...
}
  • 不要改變參數(shù)
// 為什么匈棘?因?yàn)閷?duì)象是引用類(lèi)型丧慈,操作作為參數(shù)傳入的對(duì)象,可能會(huì)在調(diào)用原始對(duì)象時(shí)造成不必要的變量副作用羹饰。

// bad
function f1(obj) {
    obj.key = 1
}
 
// good
function f2(obj) {
    const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1
}
  • 參數(shù)不要重新賦值
// bad
function f1(a) {
    a = 1
    // ...
}
 
function f2(a) {
    if (!a) { a = 1 }
    // ...
}
 
// good
function f3(a) {
    const b = a || 1
    // ...
}
 
function f4(a = 1) {
    // ...
}
  • 如果你的函數(shù)只有一個(gè)參數(shù)并且不使用大括號(hào)伊滋,則可以省略參數(shù)括號(hào)。否則队秩,為了清晰和一致性笑旺,總是給參數(shù)加上括號(hào)
// bad
[1, 2, 3].map((x) => x * x)
 
// good
[1, 2, 3].map(x => x * x)
 
// good
[1, 2, 3].map(number => (
    `A long string with the ${number}. It’s so long that we don’t want it to take up space on the .map line!`
))
 
// bad
[1, 2, 3].map(x => {
    const y = x + 1
    return x * y
})
 
// good
[1, 2, 3].map((x) => {
    const y = x + 1
    return x * y
})
  • 一個(gè)地方只在一個(gè)路徑中 import(導(dǎo)入)
// bad
import foo from 'foo'
// … 其他一些 imports … //
import { named1, named2 } from 'foo'
 
// good
import foo, { named1, named2 } from 'foo'
 
// good
import foo, {
    named1,
    named2,
} from 'foo'
  • 將所有 import 導(dǎo)入放在非導(dǎo)入語(yǔ)句的上面
// bad
import foo from 'foo'
foo.init()
 
import bar from 'bar'
 
// good
import foo from 'foo'
import bar from 'bar'
 
foo.init()
  • 不要使用 iterators(迭代器) 。請(qǐng)使用高階函數(shù)馍资,例如 map() 和 reduce() 等?筒主,而不是像 for-in 或 for-of 這樣的循環(huán)
// 為什么? 這是強(qiáng)制執(zhí)行我們不變性的規(guī)則鸟蟹。 處理返回值的純函數(shù)比副作用更容易推理乌妙。

// 使用 map() / every() / filter() / find() / findIndex() / reduce() / some() / … 來(lái)迭代數(shù)組, 使用 Object.keys() / Object.values() / Object.entries() 來(lái)生成數(shù)組,以便可以迭代對(duì)象建钥。

const numbers = [1, 2, 3, 4, 5]
 
// bad
let sum = 0;
for (let num of numbers) {
    sum += num
}
sum === 15
 
// good
let sum = 0
numbers.forEach((num) => {
    sum += num
});
sum === 15
 
// best
const sum = numbers.reduce((total, num) => total + num, 0);
sum === 15
 
// bad
const increasedByOne = [];
for (let i = 0; i < numbers.length; i++) { increasedByOne.push(numbers[i] + 1); } // good const increasedByOne = []; numbers.forEach((num) => {
    increasedByOne.push(num + 1)
})
 
// best
const increasedByOne = numbers.map(num => num + 1)
  • 使用 const 或 let聲明每個(gè)變量
const items = getItems()
const goSportsTeam = true
const dragonball = 'z'
  • 避免使用一元遞增和遞減運(yùn)算符(++, --)
let a = 1

// bad
a++

// good
a += 1
  • 盡量使用 === 和 !== 而非 == 和 !=

  • 在 case 和 default 子句中藤韵,使用大括號(hào)來(lái)創(chuàng)建包含詞法聲明的語(yǔ)句塊

// bad
switch (foo) {
    case 1:
    let x = 1;
    break
    case 2:
    const y = 2;
    break
    case 3:
    function f() {
        // ...
    }
    break
    default:
    class C {}
}
 
// good
switch (foo) {
    case 1: {
    let x = 1;
    break
    }
    case 2: {
    const y = 2;
    break
    }
    case 3: {
    function f() {
        // ...
    }
    break
    }
    case 4:
    bar()
    break
    default: {
    class C {}
    }
}
  • 三元表達(dá)式不應(yīng)該嵌套,通常寫(xiě)成單行表達(dá)式
// bad
const foo = maybe1 > maybe2
    ? "bar"
    : value1 > value2 ? "baz" : null
 
// 拆分成2個(gè)分離的三元表達(dá)式
const maybeNull = value1 > value2 ? 'baz' : null
 
// better
const foo = maybe1 > maybe2
    ? 'bar'
    : maybeNull
 
// best
const foo = maybe1 > maybe2 ? 'bar' : maybeNull
  • 避免不必要的三元表達(dá)式語(yǔ)句
// bad
const foo = a ? a : b
const bar = c ? true : false
const baz = c ? false : true
 
// good
const foo = a || b
const bar = !!c
const baz = !c
  • 當(dāng)運(yùn)算符混合在一個(gè)語(yǔ)句中時(shí)熊经,請(qǐng)將其放在括號(hào)內(nèi)泽艘。混合算術(shù)運(yùn)算符時(shí)镐依,不要將 和 % 與 + 匹涮, -,*槐壳,/ 混合在一起
// bad
const foo = a && b < 0 || c > 0 || d + 1 === 0
 
// bad
const bar = a ** b - 5 % d
 
// bad
if (a || b && c) {
    return d
}
 
// good
const foo = (a && b < 0) || c > 0 || (d + 1 === 0)
 
// good
const bar = (a ** b) - (5 % d)
 
// good
if ((a || b) && c) {
    return d
}
 
// good
const bar = a + b / c * d
  • 如果一個(gè) if 塊總是執(zhí)行一個(gè) return 語(yǔ)句然低,后面的 else 塊是不必要的。在 else if 塊中的 return务唐,可以分成多個(gè) if 塊來(lái) return
// bad
function foo() {
    if (x) {
    return x
    } else {
    return y
    }
}
 
// bad
function cats() {
    if (x) {
    return x
    } else if (y) {
    return y
    }
}
 
// bad
function dogs() {
    if (x) {
    return x
    } else {
    if (y) {
        return y
    }
    }
}
 
// good
function foo() {
    if (x) {
    return x
    }
 
    return y
}
 
// good
function cats() {
    if (x) {
    return x
    }
 
    if (y) {
    return y
    }
}
 
//good
function dogs(x) {
    if (x) {
    if (z) {
        return y
    }
    } else {
    return z
    }
}
  • 在大括號(hào)前放置 1 個(gè)空格
// bad
function test(){
    console.log('test')
}
 
// good
function test() {
    console.log('test')
}
 
// bad
dog.set('attr',{
    age: '1 year',
    breed: 'Bernese Mountain Dog',
})
 
// good
dog.set('attr', {
    age: '1 year',
    breed: 'Bernese Mountain Dog',
})
  • 在控制語(yǔ)句(if雳攘、while 等)的小括號(hào)前放一個(gè)空格。在函數(shù)調(diào)用及聲明中枫笛,不在函數(shù)的參數(shù)列表前加空格
// bad
if(isJedi) {
    fight ()
}
 
// good
if (isJedi) {
    fight()
}
 
// bad
function fight () {
    console.log ('Swooosh!')
}
 
// good
function fight() {
    console.log('Swooosh!')
}
  • 使用空格把運(yùn)算符隔開(kāi)
// bad
const x=y+5
 
// good
const x = y + 5
  • 在文件末尾插入一個(gè)空行

  • 在聲明語(yǔ)句的開(kāi)始處就執(zhí)行強(qiáng)制類(lèi)型轉(zhuǎn)換

  • 創(chuàng)建字符串

// => this.reviewScore = 9
 
// bad
const totalScore = new String(this.reviewScore) // typeof totalScore 是 "object" 而不是 "string"
 
// bad
const totalScore = this.reviewScore + '' // 調(diào)用 this.reviewScore.valueOf()
 
// bad
const totalScore = this.reviewScore.toString() // 不能保證返回一個(gè)字符串
 
// good
const totalScore = String(this.reviewScore)
  • 數(shù)字: 使用 Number 進(jìn)行轉(zhuǎn)換来农,而 parseInt 則始終以基數(shù)解析字串
const inputValue = '4'
 
// bad
const val = new Number(inputValue)
 
// bad
const val = +inputValue
 
// bad
const val = inputValue >> 0
 
// bad
const val = parseInt(inputValue)
 
// good
const val = Number(inputValue)
 
// good
const val = parseInt(inputValue, 10)
  • 創(chuàng)建布爾值
const age = 0
 
// bad
const hasAge = new Boolean(age)
 
// good
const hasAge = Boolean(age)
 
// best
const hasAge = !!age
  • 避免使用單字母名稱(chēng)。使你的命名具有描述性

  • 當(dāng)命名對(duì)象崇堰,函數(shù)和實(shí)例時(shí)使用駝峰式命名

  • 當(dāng)命名構(gòu)造函數(shù)或類(lèi)的時(shí)候使用單詞首字母大寫(xiě)方式命名

  • 將綁定數(shù)據(jù)到事件時(shí) (不論是 DOM 事件還是其他像Backbone一類(lèi)的事件), 傳遞 hash 而不是原始值沃于。 這將允許后續(xù)的貢獻(xiàn)者不用查找和更新事件的每一個(gè)處理程序就可以給事件添加更多的數(shù)據(jù)

// bad
$(this).trigger('listingUpdated', listing.id)
 
// ...
 
$(this).on('listingUpdated', (e, listingId) => {
    // do something with listingId
})

// good
$(this).trigger('listingUpdated', { listingId: listing.id })
 
// ...
 
$(this).on('listingUpdated', (e, data) => {
    // do something with data.listingId
})
  • Number.isNaN 代替全局 isNaN
// 為什么涩咖?全局的 isNaN 方法會(huì)將非數(shù)字轉(zhuǎn)換為數(shù)字, 任何被轉(zhuǎn)換為 NaN 的東西都會(huì)返回 true

// bad
isNaN('1.2') // false
isNaN('1.2.3') // true
 
// good
Number.isNaN('1.2.3') // false
Number.isNaN(Number('1.2.3')) // true
  • Number.isFinite 代替全局 isFinite
// 為什么?全局的 isFinite 方法會(huì)將非數(shù)字轉(zhuǎn)換為數(shù)字, 任何被轉(zhuǎn)換為有限大的數(shù)字都會(huì)返回 true 


// bad
isFinite('2e3') // true
 
// good
Number.isFinite('2e3') // false
Number.isFinite(parseInt('2e3', 10)) // true
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末繁莹,一起剝皮案震驚了整個(gè)濱河市檩互,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌咨演,老刑警劉巖闸昨,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異薄风,居然都是意外死亡饵较,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)遭赂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)循诉,“玉大人,你說(shuō)我怎么就攤上這事撇他∏衙ǎ” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵困肩,是天一觀的道長(zhǎng)划纽。 經(jīng)常有香客問(wèn)我,道長(zhǎng)锌畸,這世上最難降的妖魔是什么勇劣? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮潭枣,結(jié)果婚禮上芭毙,老公的妹妹穿的比我還像新娘。我一直安慰自己卸耘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布粘咖。 她就那樣靜靜地躺著蚣抗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瓮下。 梳的紋絲不亂的頭發(fā)上翰铡,一...
    開(kāi)封第一講書(shū)人閱讀 51,462評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音讽坏,去河邊找鬼锭魔。 笑死,一個(gè)胖子當(dāng)著我的面吹牛路呜,可吹牛的內(nèi)容都是我干的迷捧。 我是一名探鬼主播织咧,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼漠秋!你這毒婦竟也來(lái)了笙蒙?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤庆锦,失蹤者是張志新(化名)和其女友劉穎捅位,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體搂抒,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡艇搀,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了求晶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片焰雕。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖誉帅,靈堂內(nèi)的尸體忽然破棺而出淀散,到底是詐尸還是另有隱情,我是刑警寧澤蚜锨,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布档插,位于F島的核電站,受9級(jí)特大地震影響亚再,放射性物質(zhì)發(fā)生泄漏郭膛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一氛悬、第九天 我趴在偏房一處隱蔽的房頂上張望则剃。 院中可真熱鬧,春花似錦如捅、人聲如沸棍现。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)己肮。三九已至,卻和暖如春悲关,著一層夾襖步出監(jiān)牢的瞬間谎僻,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工寓辱, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留艘绍,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓秫筏,卻偏偏與公主長(zhǎng)得像诱鞠,于是被迫代替她去往敵國(guó)和親挎挖。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容