箭头函数就是个简写形式的函数表达式,并且它拥有继承自外部作用域的this值。此外,箭头函数总是匿名的。
基本用法
箭头函数引入了一种新的编写函数的语法:
| 1 2 3 4 5 6 7
 | var showname = function (name) {     return name; }; var showName = name => name;
 | 
这使得当我们声明只有一个参数的简单函数时,可以使用新标准中的=>表达式,我们无需输入function和return。
多个参数
如果我们的函数具有多个参数,或者没有参数,我们需要使用小括号包裹起来参数列表。
| 1 2 3 4 5 6 7
 | var tatal = values.reduce(function (a, b) {     return a + b; }, 0); var total = values.reduce((a, b) => a + b, 0);
 | 
语句块
箭头函数不仅仅能包含一个表达式,还可以包含一个语句块,语句块用{}来包裹起来。
但是,如果函数体为语句块,那么函数将不会自动添加return语句。因此,这时候我们如果想返回什么东西,必须显式声明return语句。
| 1 2 3 4
 | var showNum = num => {     num ++;     return num; };
 | 
返回普通对象
假如我们需要用箭头函数来返回一个普通对象时,我们需要将对象包裹在小括号里。
| 1 2
 | var myObj = (name, age) => {};     var myObje = (name, age) => ({})  
 | 
因为一个普通对象和语句块都是使用{}来包裹的,看起来很像。而ES6规定,总是将{看作一个语句块的开始,而非一个对象的开始。因此name => {} 被默认解释为一个什么都没有做,并且返回undefined的箭头函数。
this
在严格模式下,全局作用域下定义的函数中,this指向undefined。
在非严格模式下,全局作用域下定义的函数中,this指向window。
而在箭头函数中,this没有值,箭头函数内部的this值继承自外围作用域。
我们先来回顾一下平时使用this的场景:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14
 | 'use strict'; var person = {   name: 'xuwenjiang',   love: ['aaa', 'bbb', 'ccc'],   show: function () {     console.log(this);             this.love.forEach(function (item) {       console.log(this);           });   } }; person.show();
 | 
以上代码,在内部函数中,没有继承外部函数的this指向,所以在严格模式下,this为undefined。
为了让内部函数的this也指向person对象,我们经常这么干:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
 | 'use strict'; var person = {   name: 'xuwenjiang',   love: ['aaa', 'bbb', 'ccc'],   show: function () {          var self = this;               console.log(this);             this.love.forEach(function (item) {              console.log(self);         });   } }; person.show();
 | 
这样可以解决问题,但是这样麻烦不?很显然,麻烦。
ES6中,我们可以更好地解决这个问题,但是我们需要遵循以下规则:
- 对于object.method()形式的函数,使用非箭头函数语法。这些函数在运行时将会接受到一个有意义的this值,this指向他们的调用者。
- 其他函数统一使用箭头函数。
所以,以上代码可以利用箭头函数重写:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
 | 'use strict'; var person = {   name: 'xuwenjiang',   love: ['aaa', 'bbb', 'ccc'],      show: function () {         console.log(this);                  this.love.forEach((item) => {       console.log(this);         });   } }; person.show();
 | 
更简洁的方式
超赞的是,在ES6中,我们可以使用更加简洁的方式编写对象字面量中的方法,以上代码可以简化成:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
 | 'use strict'; var person = {   name: 'xuwenjiang',   love: ['aaa', 'bbb', 'ccc'],      show () {         console.log(this);             this.love.forEach((item) => {       console.log(this);         });   } }; person.show();
 | 
没有arguments对象
箭头函数和非箭头函数还有第二个小小的区别:箭头函数也没有他们自己的arguments对象。
但是,在es6中,我们可以使用剩余参数来代替,案例如下;
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 | var getSum = function () {   var sum = 0;   for (var i = 0; i < arguments.length; i ++) {     sum += arguments[i];   }   return sum; }; var getSum = (...rest) => {   var sum = 0;   for (let i = 0; i < rest.length; i ++) {     sum += rest[i];   }   return sum; } console.log(getSum(1,2,3,4,5));    
 | 
这里也简单总结下剩余参数和arguments对象的区别:
- 剩余参数只包含那些没有对应形参的实参,而arguments对象包含了传给函数的所有实参。
- arguments对象不是一个真实的数组了,而剩余参数是一个真实的Array实例,也就是说,你可以在它上面直接使用所有的数组方法。
- arguments对象还有一些附加的属性,比如callee。
参考资料