-- 接 JavaScript 风格指南(2) --
七、Functions
· 7.1 使用命名函数表达式,而不是函数声明
理由:函数声明提升会导致在函数定义之前就已经可以引用该函数了,这会损害可读性和可维护性。如果想要定义的函数很复杂,复杂到会干扰理解代码的其余部分,应该考虑将其解压缩到自己的模块中了!不要忘记给表达式命名——匿名函数不利于错误的定位。
// bad
function foo() {
// ...
}
// bad
const foo = function () {
// ...
};
// good
const foo = function bar() {
// ...
};
· 7.2 立即调用函数应该用圆括号包裹起来
理由:这样的表达更干净整洁,它就是一个独立的模块。
// immediately-invoked function expression (IIFE)
(function () {
console.log('Welcome to the Internet. Please follow me.');
}());
· 7.3 不要在非函数模块中声明函数(如 if、while 语句中),尽管浏览器允许你这么做,但是不同浏览器的解释会有所不同。应该把函数赋值给一个变量。
· 7.4 在 ECMA-262 定义的块语句列表中,函数声明不是语句。
// bad
if (currentUser) {
function test() {
console.log('Nope.');
}
}
// good
let test;
if (currentUser) {
test = () => {
console.log('Yup.');
};
}
· 7.5 永远不要将参数命名为 arguments,因为它会覆盖实际的参数对象。
// bad
function foo(name, options, arguments) {
// ...
}
// good
function foo(name, options, args) {
// ...
}
· 7.6 如果要使用参数的话,用 ... 扩展运算符吧,别用 arguments 对象,毕竟 ... 得到的是纯数组而不是类数组对象
// bad
function concatenateAll() {
const args = Array.prototype.slice.call(arguments);
return args.join('');
}
// good
function concatenateAll(...args) {
return args.join('');
}
· 7.7 给参数一个默认值,别等到用的时候去做判断,这样会使函数参数发生改变
// really bad
function handleThings(opts) {
// 绝对不要!我们不应该改变函数参数
// 如果 opts 本身就是一个 falsy 对象,下面的判断就会导致 bug 出现
opts = opts || {};
// ...
}
// still bad
function handleThings(opts) {
if (opts === void 0) {
opts = {};
}
// ...
}
// good
function handleThings(opts = {}) {
// ...
}
· 7.8 函数参数的默认值不要有副作用
理由:这样会导致表达含混不清
var b = 1;
// bad
function count(a = b++) {
console.log(a);
}
count(); // 1
count(); // 2
count(3); // 3
count(); // 3
· 7.9 带默认值的参数放到最后
// bad
function handleThings(opts = {}, name) {
// ...
}
// good
function handleThings(name, opts = {}) {
// ...
}
· 7.10 别用构造函数去创建新函数
理由:如果传入构造函数中的参数如果是字符串,会引入 eval()
// bad
var add = new Function('a', 'b', 'return a + b');
// still bad
var subtract = Function('a', 'b', 'return a - b');
· 7.11 在函数名前后敲个空格
理由:保持良好的一致性,在添加或删除名称时不必添加或删除空格。
// bad
const f = function(){};
const g = function (){};
const h = function() {};
// good
const x = function () {};
const y = function a() {};
· 7.12 不要对函数的参数做出改变
理由:改变作为参数传入的对象会导致意想不到的副作用
// bad
function f1(obj) {
obj.key = 1;
}
// good
function f2(obj) {
const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1;
}
· 7.13 别对函数参数重新赋值
理由:对参数重新赋值会引发不可预料的后果,特别是在访问 arguments 对象时,由此也有引出 js 引擎优化的话题,尤其是在 V8 下。
// 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) {
// ...
}
· 7.14 扩展运算符 ... 的使用会使问题变得很简单
// bad
const x = [1, 2, 3, 4, 5];
console.log.apply(console, x);
// good
const x = [1, 2, 3, 4, 5];
console.log(...x);
// bad
new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5]));
// good
new Date(...[2016, 8, 5]);
· 7.15 如果函数参数有很多项,应该分多行书写
// bad
function foo(bar,
baz,
quux) {
// ...
}
// good
function foo(
bar,
baz,
quux,
) {
// ...
}
// bad
console.log(foo,
bar,
baz);
// good
console.log(
foo,
bar,
baz,
);
参考文章:
JavaScript 风格指南
--未完待续--