本文基于《阿里巴巴JavaScript编程规约》、ESLint rules进行编写。
参考资料:javascript: JavaScript 规范,虽然不一定完全遵守,但是值得学习一下
分号
统一以分号结束语句,可以避免 JS 引擎自动分号插入机制的怪异行为,在语义上也更加明确。
自动分号插入机制
自动分号插入机制(即
Automatic Semicolon Insertion
,简称
ASI
) 是当
JS
遇到不带分号
的语句时判断是否自动添加分号的机制,它在个别情况下的行为比较怪异,可能导致意想不
到的效果。此外随着
JS
新特性的增加,异常的情况可能变得更加复杂。
// 以下代码会导致 Uncaught ReferenceError 报错
const luke = {}
const leia = {}
[luke, leia].forEach((jedi) => {
jedi.father = 'vader'
})
// 以下代码会导致 Uncaught ReferenceError 报错
const reaction = "No! That's impossible!"
(async function meanwhileOnTheFalcon() {
}())
空格
可以按照vs code快捷方式shift+alt+f空格展示
if (foo) {
thing1();
} else {
thing2();
}
try {
// …
} catch (e) {
}
中括号和小括号内部两侧不空格,大括号内部两侧空格
if (foo) {
console.log(foo);
}
const foo = [1, 2, 3];
const foo = { clark: 'kent' };
换行
块的内部开始和结束不换行
function bar() {
console.log(foo);
}
块结束和新的语句之间换行
if (foo) {
return bar;
}
return baz;
遇到注释要先换行
console.log('fetching type...');
// set the default type to 'no type'
const type = this.type || 'no type';
多个条件语句换行
const foo = jsonData
&& jsonData.foo
&& jsonData.foo.bar
&& jsonData.foo.bar.baz
&& jsonData.foo.bar.baz.quux
&& jsonData.foo.bar.baz.quux.xyzzy;
Ajax请求换行
$.ajax({
method: 'POST',
url: 'https://foo.com/',
data: { name: 'John' },
})
.done(() => console.log('Congratulations!'))
.fail(() => console.log('You have failed this city.'));
语言风格
变量声明
const和let
不需要重新赋值的变量优先使用const
需注意,数组和对象是一个引用,对数组某项和对象某属性的修改并不是重新赋值
建议
一条语句声明一个变量
便于修改,用逗号的形式不便于后期代码修改
const foo = 1;
const bar = 2;
变量声明尽量不要同名
如果变量与外层已存在变量同名,会降低可读性,也会导致内层作用域无法读取外层作用域的同名
变量。
const foo = 1;
if (someCondition) {
const bar = 2;
console.log(bar); // => 2
console.log(foo); // => 1
}
不要连续赋值
变量的连续赋值让人难以阅读和理解,并且可能导致意想不到的结果(如产生全局变量)。
(function test() {
/**
* 相当于 let a = (b = (c = 1));
* b和c变为全局变量
*/
let a = b = c = 1;
})();
console.log(a); // throws ReferenceError
console.log(b); // 1
console.log(c); // 1
字符串
使用模板字符串替代字符串拼接
提升代码可读性
function getDisplayName({ nickName, realName }) {
return `${nickName} (${realName})`;
}
禁止不必要的转义字符
转义字符会大大降低代码的可读性,因此尽量不要滥用它们
//no
const foo = '\'this\' \i\s \"quoted\"';
// yes
const foo = `'this' is "quoted"`;
不要使用 new Number
使用
new Number/String//Boolean
声明不会有任何好处,还会导致变量成为
object
类型,可
能引起
bug
const num = new Number(0);
const str = new String('foo');
const bool = new Boolean(false);
console.log(typeof num, typeof str, typeof bool); // => object, object,
使用显示类型转换
不要依赖于
==
和
!=
的隐式类 型转换
扩展运算符
使用扩展运算符...处理数组和对象
const array1 = [...array];
// 可以利用 Set 和 ... 将数组去重
const uniqueNodes = [...new Set(foo)];
//数组拼接
const array1 = [1, 2, ...array];
// 替代apply
const args = [1, 2, 3, 4];
Math.max(...args); // Math.max.apply(Math, args);
//使用解构获取数组元素
const arr = [1, 2, 3, 4];
const [first, second] = arr;
特殊的,遍历可迭代对象时, 使用
Array.from
而不是
...
,以免创建一个临时数组:
const baz = Array.from(foo, bar);
对象的属性名不要用引号包裹
对象的属性名不要用引号包裹,除非包含特殊字符。
这样更加简洁,也有助于语法高亮和一些
JS
引擎的优化。
const good = {
foo: 3,
bar: 4,
'data-blah': 5,
'one two': 12,
};
注释风格
单行//
多行/**...*/
/**
* make() returns a new element
* based on the passed-in tag name
*/
注意空格
函数注释
简单注释
/**
* 用户注册
* @param {string} username 用户名
* @param {string} password 密码
*/
function register(username, password) {
// ...
}
复杂注释
/**
* 购买图书
* @param {Object} book
* @param {string} book.title
* @param {string} book.author
*/
function buyBook(book) {
// ...
}
写法2
// 声明复杂数据类型,降低注释工作量,可重复使用
/**
* @typedef {Object} Book 图书
* @property {string} title 标题
* @property {string} author 作者
*/
/**
* 购买图书
* @param {Book} book
*/
function buyBook(book) {
// ...
}
返回值注释
/**
* 测试函数
* @return {number} 返回值
*/
function test () {
// ...
}
持续更新中。。。