Python中的一些規範,比如google編碼規範,可能沒有PEP8那麼被大家廣爲所知,但是JS就不一樣了,Airbnb Javascript相比起來就是廣爲人知的一種規範。最近因爲獵奇心一直在學習各種各樣新鮮的東西,這幾天興趣漸漸消退,我們還是回到需要夯實的基礎上面吧,今天就來看一下Airbnb Javascript。
講到這裏大家可能對pythonic和PEP8優點混淆,對於Python來說,我的理解是前者是一種語法層面的規範,怎樣的語法更簡單易懂更加井然有序;後者則是排版上的一些規範,較爲熟知的有4個空格的縮進,不要在一句import中多個庫,各種右括號前不要加空格等等,當然PEP不僅如此,要非用一句話來概括得話,我覺得Pythonic更偏向於經驗所得,而PEP8則是權威蓋了個章。
那對於Javascript來說呢?
我想大家應該都用過一些腳手架工具,Eslint中會提供各種各樣的風格的選項,Standard,或者Airbnb或者其他,其中,Airbnb算是其中最受歡迎的一種了,這裏較爲詳細的介紹我認爲大家應該關注的點:
// bad
const item = new Object();
// good
const item = {};
對於上述創建對象的語句,前者是不適合的。
// bad
const atom = {
value: 1,
addValue: function (value) {
return atom.value + value;
},
};
// good
const atom = {
value: 1,
addValue(value) {
return atom.value + value;
},
};
官網叫做函數速記的風格,下文還有屬性速記的說法:
const lukeSkywalker = 'Luke Skywalker';
// bad
const obj = {
lukeSkywalker: lukeSkywalker,
};
// good
const obj = {
lukeSkywalker,
};
下面這種設計方法是我一直犯錯的地方,對於無效的標識符屬性才使用引號,據說這樣能更好的閱讀。
// bad
const bad = {
'foo': 3,
'bar': 4,
'data-blah': 5,
};
// good
const good = {
foo: 3,
bar: 4,
'data-blah': 5,
};
創建數組時也一樣:
// bad
const items = new Array();
// good
const items = [];
更多的使用push方法:
const someStack = [];
// bad
someStack[someStack.length] = 'abracadabra';
// good
someStack.push('abracadabra');
複製數據時最好選擇後者的方式:
// bad
const len = items.length;
const itemsCopy = [];
let i;
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i];
}
// good
const itemsCopy = [...items];
對於對象多個屬性進行解構:
// 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}`;
}
數組結構:
const arr = [1, 2, 3, 4];
// bad
const first = arr[0];
const second = arr[1];
// good
const [first, second] = arr;
又或是返回值結構,我們可以任選返回值,而不用在意出現的次序等問題。
// bad
function processInput(input) {
// then a miracle occurs
return [left, right, top, bottom];
}
// the caller needs to think about the order of return data
const [left, __, top] = processInput(input);
// good
function processInput(input) {
// then a miracle occurs
return { left, right, top, bottom };
}
// the caller selects only the data they need
const { left, top } = processInput(input);
對於字符串使用單引號就不說了,還有包括``模板字符串的使用,而不是去串聯字符串。
對於function,我們應該儘可能使用函數聲明而不是函數表達式。
// bad
const foo = function () {
};
// good
function foo() {
}
函數參數這一部分,使用默認參數要小心副作用,同時還將其設置到最後:
// bad
function handleThings(opts = {}, name) {
// ...
}
// good
function handleThings(name, opts = {}) {
// ...
}
如果你的函數只有一個參數且不使用大括號,則省略括號:
// bad
[1, 2, 3].map((x) => x * x);
// good
[1, 2, 3].map(x => x * x);
否則就使用括號:
// 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;
});
儘可能使用class,而不要使用原型鏈直接操控。包括其他的語法糖如extends,這些都是未來會流傳的做法
import和export也是我們的未來,但是儘量不要使用通配符。
// bad
const AirbnbStyleGuide = require('./AirbnbStyleGuide');
module.exports = AirbnbStyleGuide.es6;
// ok
import AirbnbStyleGuide from './AirbnbStyleGuide';
export default AirbnbStyleGuide.es6;
// best
import { es6 } from './AirbnbStyleGuide';
export default es6;
還有與PEP相反的從多處導入導出:
// bad
import foo from 'foo';
// … some other imports … //
import { named1, named2 } from 'foo';
// good
import foo, { named1, named2 } from 'foo';
// good
import foo, {
named1,
named2,
} from 'foo';
關於迭代,for-in和for-of並不是我們最推薦的,
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 (use the functional force)
const sum = numbers.reduce((total, num) => total + num, 0);
sum === 15;
關於訪問屬性,使用點來表示:
const luke = {
jedi: true,
age: 28,
};
// bad
const isJedi = luke['jedi'];
// good
const isJedi = luke.jedi;
比較符號,不要再用“==”和“!=”了。
和Python不同,注意[]也是true,但是字符串和數字時一樣的。
其他包括縮進兩個空格, () {}之間需要有一個空格,還有下面空格的設置:
// bad
const x=y+5;
// good
const x = y + 5;
最後,函數和實例時使用駝峯命名,構造函數或類時使用首字母大寫,這個相對來說我覺得更看習慣吧,我個人還是喜歡下劃線的寫法。