函数的扩展

ES6增加了很多函数语法糖,使得JavaScript的编写更为简练。

 

函数参数的默认值

ES6中可以为函数配置默认参数。

示例

示例1

// ES5
var x = 1;
function test(y) { y = y || x; };
// ES6
var x = 1;
function test(y = x) {...};
test();

示例2

// ES6
var x = 1;
function test(x, y = function(){
  x = 2;
  console.log(x); // 2
}) {
  var x = 3;
  y();
  console.log(x); // 3
}
test();
console.log(x); // 1

注意事项

  • 如果有多个参数的情况下,推荐的做法是把需要设置默认值的参数放到最后
  • 每个函数都有个length方法,该方法返回没有设置默认值的参数个数
  • 在ES6中引入了块级作用域的概念,在示例2中(当默认参数是函数时),一共有三个作用域空间:
    • 全局作用域
    • 函数作用域
    • ES6新引入的有条件的参数立即作用域

对于全局与函数作用域,这两个概念相信大家不会陌生,在ES5中由于没有默认参数的概念,也就更没有默认参数为函数的情况,所以ES5中参数与函数共享函数作用域。在ES6中当函数有默认参数时,为了存储这些参数ES6会定义一个立即作用域,并且这个作用域不会与函数作用域共享。

  • “立即”:ECMAScript在每次函数调用的执行期才会计算默认值,计算完毕后,这个作用域就会被销毁
  • “有条件”:ES6中的函数没有默认参数时,就不会创建这个参数立即作用域的

引入参数立即作用域的原因是为了不污染双方函数的变量环境,清晰逻辑,各管各互不影响,比如构成闭包的时候。 如:

var x = 1;
function test(x, y = function(){
  var x = 2;
  return x;
}) {
  var x = 3;
  return y();
}
test(); // 2 这里的默认参数的y函数构成一个闭包需要返回y函数内部的x值,如果没有参数y函数与test函数是共享作用域的,这时test函数对x的重新赋值会影响到y函数的内部x值,这样输出的就是test函数中重新赋值的3。

rest参数

ES6引入rest运算符(…),创建可变参数,一个参数代表多个参数。

示例

function sum (results, ...values) {
  values.forEach((value) => results += value);
  return results;
}
sum(0,1,2,3,4,5,6) // 21

注意事项

  • 需要使用rest参数时应该将这个参数放到最后
  • 函数的length属性不包括rest参数

扩展运算符(spread)

spread,将一个参数展开为多个参数,与rest相反,多个参数代表为一个参数。

示例

var a = [1, 2, 3];
var b = [4, 5, 6, 7, 8];
var number = [ ...a, ...d]; // [1, 2, 3, 4, 5, 6, 7, 8]

[...'hello'] // [ "h", "e", "l", "l", "o" ]

箭头函数

arrow(箭头函数)ES6新引入的定义函数的方式。

示例

 
// 循环体里就是一个箭头函数
function sum (results, ...values) {
  values.forEach((value) => results += value);
  // 或者 values.forEach((value) => {results += value;});
  return results;
}

箭头函数使得函数的定义变得十分简洁,有很多代码可以用更少的行来编写,使得代码变得十分精练。

注意事项

  • 箭头函数的this对象式固定的,不像传统函数那样可变(谁调用this就是谁),箭头函数的this是开始定义时所在的对象
  • 箭头函数不能当成构造函数使用
  • 不可以使用arguments对象,也不能使用yield命令