【ES6系列】函数部分

箭头函数

在以前ES5的版本中,咱们定义一个函数的形式以下:数组

function a() {
  // do something……
}

可是在ES6中,则新增了箭头函数的方式,ES6中容许使用“箭头”(=>)来定义函数。函数

() => {
  // do something……
}

其中()中表明的是参数部门,{}中是函数体部分。
若是箭头函数不须要参数或者须要多个参数时,须要使用一个()来包裹,当只有一个参数时,能够省略()工具

var f = () => 5;
// 等同于
var f = function () { return 5 };

var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
  return num1 + num2;
};

var f = v => v;

// 等同于
var f = function (v) {
  return v;
};

当咱们在函数中返回一个对象时,以前的写法是:优化

var f = function(id) {
  return {
    id: id,
    name: "name"
  }
}

此时若是改成箭头函数的方式来写时,须要注意的是,因为在ES6中{}表明了一个代码块,因此在返回一个对象的时候,须要在对象{}外面使用括号包起来:this

let f = id => ({id: id, name: "name"})

若是箭头函数只有一行语句,且不须要返回值,能够采用下面的写法,就不用写大括号了。spa

let fn = () => void doesNotReturn();

不难发现,ES6中的箭头函数相对ES5中的函数的写法更加的简洁方便prototype

const isEven = n => n % 2 == 0;
const square = n => n * n;

如上面只是简单地两行,就定义了两个经常使用的工具函数。按照以前的写法则会书写多行。特别是在针对回调函数的时候,更可以起到简化的做用:rest

// ES5的写法
var evens = [1,2,3,4,5];
var odds = evens.map(function(v){
  return v + 1
})

// ES6的写法

let evens = [1,2,3,4,5];
let odds = evens.map(v => v + 1)

箭头函数的this的绑定

箭头函数和普通函数的另外一个区别,在于this的绑定。例如:code

var factory = function() {
  this.a = "a";
  this.b = "b";
  this.c = {
    a : "a+",
    b : function() {
      return this.a
    }
  }
}
console.log(new factory().c.b()) // "a+"

经过上面的代码执行能够看出,获得的结果是“a+”,从而能够看出this.a指向的是c.a。有人曾总结过this的指向是该函数被调用的对象。此处b是c调用的,因此指向c中的a。如今修改成ES6的箭头函数的写法:对象

let factory = function() {
  this.a = "a";
  this.b = "b";
  this.c = {
    a : "a+",
    b : () => {
      return this.a
    }
  }
}
console.log(new factory().c.b()) // "a"

执行上面的代码发现,输出的结果是“a”,这又是为何呢?请看下图所示
图片描述

注意点

箭头函数有几个使用注意点

  • (1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。这个咱们在上面的例子中也已经见到过了,再举一个比较常见的例子:

在涉及到setTimeout和setInterval时,咱们以前的方法是在调用前将函数体内的this经过赋值给一个变量的方法,使得可以在setTimeout和setInterval的回调函数中使用函数体的this

function foo() {
  this.id = "111"; 
  var _this = this;

  setTimeout(function () {
    console.log('id:', _this.id);
  }, 100);
}

可是在ES6中在使用箭头函数以后则再也不须要进行赋值替换而能直接使用函数体中的this

function foo() {
  this.id = "111"; 
  setTimeout(()=>{
      console.log(this.id);
  }, 100);
}

this指向的固定化,并非由于箭头函数内部有绑定this的机制,实际缘由是箭头函数根本没有本身的this,致使内部的this就是外层代码块的this。正是由于它没有this,因此也就不能用做构造函数。

除了this,如下三个变量在箭头函数之中也是不存在的,指向外层函数的对应变量:arguments、super、new.target

  • (2)不能够看成构造函数,也就是说,不可使用new命令,不然会抛出一个错误。
  • (3)不可使用arguments对象,该对象在函数体内不存在。若是要用,能够用 rest 参数代替(下面会讲解rest参数)。
  • (4)不可使用yield命令,所以箭头函数不能用做 Generator 函数,这部分在后面具体遇到时再进行说明。

函数的默认参数

对于带有参数的函数,咱们每每在一些状况下须要给出一个默认值的设置,当不传入参数时,也能确保函数可以正常执行。在ES5中,咱们的写法每每以下:

function f(x, y, z) {
  if(y === undefined) {
    y = 7;
  }
  if(z === undefined) {
    z = 5;
  }
  return x + y + z
}
console.log(f(1,3));

在ES6中容许为函数的参数设置默认值,即直接写在参数定义的后面。

function f(x, y = 7, z = 5) {
  return x + y + z
}
console.log(f(1,3));

这段代码和上面的执行结果是一致的,能够看出函数默认值的写法使得函数定义更加的简洁清晰。
ES6 的写法还有两个好处:

  • 首先,阅读代码的人,能够马上意识到哪些参数是能够省略的,不用查看函数体或文档;
  • 其次,有利于未来的代码优化,即便将来的版本在对外接口中,完全拿掉这个参数,也不会致使之前的代码没法运行。

应用

另外,在上面的处理中,咱们并无针对x的赋值进行验证,这样当在没有给出x的值的时候,函数会致使报错。这个时候,咱们能够来写一个非空验证的方法,来给函数添加校验。

function checkParameter() {
    throw new Error('can\'t be empty')
}
function f(x = checkParameter(), y = 7, z = 5) {
  return x + y + z
}
console.log(f(1,3));
try{
  f()
} catch(e) {
  console.log(e)
} finally {
  
}

这样给x设置默认值的方式来执行校验函数,就能够确认x的赋值的有效性了。这也是函数默认值的一种使用技巧。

rest参数

上面针对参数默认值作了说明,下面咱们考虑一下一个概念,可变参数,好比咱们如今来作一个求和运算的函数,可是是几个数的求和是不必定的,按照ES5中的处理,咱们的写法:

function sum() {
  var array = Array.prototype.slice.call(arguments);
  // arguments对象不是数组,而是一个相似数组的对象。因此为了使用数组的方法,必须使用Array.prototype.slice.call先将其转为数组。
  var sum = 0;
  array.forEach(function(item){
    sum += item * 1
  })
  return sum;
}

sum(1,2,3,4)

主要是经过arguments来获取函数的参数列表来获取参数。可是在ES6中却并不须要这么麻烦,ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不须要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

function sum(...a) {
  var sum = 0;
  a.forEach(item => sum+= item*1)
  return sum;
}
sum(1,2,3,4)

经过ES6的rest参数,可以更加简洁的来实现不定参数的函数的实现。rest参数是一个真正的数组,数组特有的方法均可以使用,彻底比上面经过arguments的方法更加天然、简洁。

注:rest参数以后不能再有其余参数(即只能是最后一个参数)。

小结

本次主要针对ES6中对于函数部分的相关扩展内容做了梳理,并无很是的全面,而是选择其中比较经常使用比较重要的箭头函数、函数默认值和rest参数这几部分进行了说明。更加细致的体会仍是须要在后续的不断使用中进行增强和熟悉。
相关文章
相关标签/搜索