六维教程

ES6 函数扩展

写了这么多函数,你一定遇到过这些情况:参数不传就报 undefined、想传不确定数量的参数却不会写。

ES6 给函数带来了两个实用升级:参数默认值rest 参数...args)。

参数默认值

为什么需要默认值

看下面这个例子,不传参数时很不友好:

// ES5:不传参数,name 就是 undefined
function greet(name) {
  console.log('你好,' + name);
}
greet();          // 你好,undefined
greet('小明');    // 你好,小明

ES6 允许在定义参数时直接写默认值,没传参数时自动用它

// ES6:参数默认值
function greet(name = '访客') {
  console.log('你好,' + name);
}
greet();          // 你好,访客
greet('小明');    // 你好,小明

关键点:

  • 只传 undefined 时会用默认值;null 不会null 是”故意传空”,会被保留)。
  • 有默认值的参数最好放最后,否则调用时容易乱(见下面示例)。
// 示例:默认值放后面,调用才自然
function info(name, age = 18) {
  console.log(name + ' ' + age);
}
info('小明');        // 小明 18
info('小红', 20);    // 小红 20

// 反例:默认值放前面,想传 age 还得为 name 传 undefined
function bad(age = 18, name) {
  // ...
}
bad(undefined, '小红'); // 只能这样调用,别扭

rest 参数(...参数名

如果函数的参数数量不固定怎么办?ES5 用 arguments,ES6 用 rest 参数更直观。

// ES6:rest 参数收集"剩余的所有实参"为一个数组
function sum(...nums) {
  let total = 0;
  for (const n of nums) {
    total += n;
  }
  return total;
}
console.log(sum(1, 2));       // 3
console.log(sum(1, 2, 3, 4)); // 10

三个要点:

  1. rest 参数必须写在参数列表最后,它负责”回收剩余的参数”。
  2. 没有多余参数时,rest 是空数组 [],不会报错。
  3. 前面固定的参数照常使用:
// 示例:固定参数 + rest 参数
function log(prefix, ...rest) {
  console.log(prefix, rest);
}
log('提示', 1, 2, 3);    // 提示 [1, 2, 3]

rest 和 arguments 的区别

对比 arguments(ES5) rest 参数(ES6)
形态 类数组,不能直接用数组方法 真正的数组
是否包含全部参数 包含全部 只收”剩余”的
与固定参数次序 内部对象,不灵活 明确定义,清晰

rest 参数更推荐:它就是普通数组,能用 mapfilter 等等直接操作。

小提示:这里只介绍 rest 参数的”收集”用法。展开运算符 ...(把数组再还原成一个个参数)写法几乎一样、作用相反,在本系列”运算符扩展”篇正式介绍,方便对比记忆。

组合使用

默认值 + rest 可以一起用,覆盖面更广:

// 示例
function createUser(name = '无名', tags = [], ...others) {
  console.log('名字:' + name);
  console.log('标签:' + tags);
  console.log('其他:' + others);
}
createUser('小明', ['前端'], '男', 99);
// 名字:小明
// 标签:['前端']
// 其他:['男', 99]

常见疑问

默认值可以是任意表达式吗

可以,默认值可以是表达式,甚至可以是函数调用的结果:

// 示例
function getNow() {
  return new Date().getFullYear();
}
function logYear(year = getNow()) { // 没传时自动取当前年份
  console.log(year);
}

null 也能触发默认值吗

不能。只有 undefined 会触发默认值,null 会被原封不动保留。

上一篇
ES6 箭头函数
下一篇
ES6 字符串扩展