ES6之Function

ES6 为函数引入了很多新特性,本文将一一总结。

函数参数的默认值

ES6允许为函数的形参设定默认值,示例如下:

1
function foo(a = 0, b = 1) {}

与解构赋值的默认值类似,默认值生效条件为传入的实参值为 undefined

通常情况下,定义默认值的形参应该是函数的尾参数,代码可读性高,而且传入实参时也可只省略此参数。如果有默认值的参数不是尾参数,那么再传入实参时无法只省略此参数。所以最佳实践是将定义了默认值的参数写在函数的形参列表末尾。

有一点需要注意的是,指定了形参默认值后,函数的 length 属性会失效。其将返回没有指定默认值形参个数,另外如果设置了默认值的形参不是尾参数,那么 length 属性值也不计入后续形参。

rest参数

ES6引入了 rest参数,形式为 ...变量名, 用于获取函数的多余参数,这样就不需要使用 arguments 对象了。rest参数 搭配的变量是一个数组,该变量将多余的参数放入数组中。

1
2
3
4
5
6
7
8
function add(...values) {
let sum = 0;
for (let val of values) {
sum += val;
}
return sum;
}
add(1, 2, 3) // 6

有了 rest参数 之后,多数场景下我们就不需要使用 arguments 对象了。并且 rest参数 中的变量是一个数组,所有数组特有的方法都可用于这个变量。

需要注意的有以下几点:

  • rest参数 之后不能再有其他参数,否则会报错。
  • 函数的 length 属性值不包括 rest参数

扩展运算符(…)

扩展运算符是三个点 ...。它就好比是 rest参数的逆运算,将一个数组转为用逗号分隔的参数序列。

1
2
// 等价于 console.log(0, 1, 2)
console.log(...[0, 1, 2]); // 0 1 2

有了该运算符,我们就不再需要 apply() 方法,将数组转换为函数参数了。

本质上来说,任何实现了 Iterator 接口的对象,都可以使用扩展运算符转为真正的对象。

name属性

函数的 name 属性,返回该函数的函数名。这一点直到 ES6 才终于写入了标准。

需要注意的有以下几点:

  1. ES5中,如果将一个匿名函数赋值给一变量,其 name 属性会返回空字符串,而 ES6 中 name 属性则会返回变量名称。

    1
    2
    3
    4
    5
    const f = function() {};
    // ES5
    f.name // ""
    // ES6
    f.name // "f"
  2. Function 构造函数返回的实例,name 属性的值为 anonymous

  3. bind() 调用返回的新函数,name 属性值会加上 bound 前缀

箭头函数

ES6 允许使用 => 定义函数:

1
const add = (num1, num2) => { return num1 + num2; };

上面的箭头函数等同于:

1
2
3
const add = function(num1, num2) {
return num1 + num2;
}

从上面可以看出定义箭头函数的规则:

  • 赋值号左侧为函数名称
  • 赋值号右侧(即箭头左侧)为参数列表
  • 箭头右侧为函数体内的代码块

如果箭头函数不需要形参或需要多个形参,就是用一个圆括号包裹参数部分。如果箭头函数的代码块部分多余一条语句,就要使用大括号括起来,并且使用 return 语句返回。

如果函数的形参列表和函数体比较简单,箭头函数也可以省略圆括号、大括号和 return 关键字:

1
2
3
4
5
const f = a => a;
// 等价于
const f = function(a) {
return a;
}

这种方式有一点需要注意:返回一个对象时,应该使用圆括号将对象括起来,因为 JavaScript 引擎会将大括号解释为代码块的开始。

使用箭头函数时需要注意以下几点:

  1. 箭头函数体内的 this 对象,就是定义时所在作用域的 this,并非执行时的上下文
  2. 箭头函数不可用作构造对象,即不可使用 new 关键字调用箭头函数
  3. 箭头函数体内不存在 arguments 对象,如果需要,请使用 rest参数
  4. 箭头函数不可使用 yield 命令,因此不能用作 Generator 函数

参考