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;
最后,函数和实例时使用驼峰命名,构造函数或类时使用首字母大写,这个相对来说我觉得更看习惯吧,我个人还是喜欢下划线的写法。