[ES6] ECMAScript 6对函数的扩展-箭头函数

 2016年02月06日    190     声明


ES6中增加了箭头函数,箭头函数是简写形式的函数表达式,即:使用箭头(=>)来定义函数。箭头函数拥有词法的作用域,且总是匿名函数。


  1. 语法结构
  2. 箭头函数介绍


1. 语法结构

基本语法:

(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
//等同于
(param1, param2, …, paramN) => { return expression; }

// 如果只有一个参数,圆括号是可选的:
(singleParam) => { statements }
singleParam => { statements }

// 无参数的函数需要使用圆括号:
() => { statements }

高级语法:

// 返回对象字面量时应当用圆括号将其包起来:
params => ({foo: bar})

// 支持 Rest 参数 和 default 参数
(param1, param2, ...rest) => { statements }
(param1 = defaultValue1, param2, …, paramN = defaultValueN) => { statements }

// 参数列表同样支持解构形式
var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f();  // 6

例如,对于如下一个箭头函数:

var f = v => v;

其相当于:

var f = function(v) {
  return v;
};

几个箭头函数的使用示例:

// 一个空箭头函数,返回 undefined
let empty = () => {};

(() => "foobar")() // 返回 "foobar" 

var simple = a => a > 15 ? 15 : a; 
simple(16); // 15
simple(10); // 10

let max = (a, b) => a > b ? a : b;

// 数组的应用
var arr = [5, 6, 13, 0, 1, 18, 23];
var sum = arr.reduce((a, b) => a + b);  // 66
var even = arr.filter(v => v % 2 == 0); // [6, 0, 18]
var double = arr.map(v => v * 2);       // [10, 12, 26, 0, 2, 36, 46]


2. 箭头函数介绍

箭头函数提供了更短的函数书写形式this的词法解析

2.1 更短的函数

更短的函数书写形式,可以使代码更为简洁:

var a = [
  "itbilu.com",
  "niefengjun.cn",
  "yijiebuyi.com"
];

var a2 = a.map(function(s){ return s.length });

// 使用箭头函数代码量会相对减少
var a3 = a.map( s => s.length );


2.2 this的词法

在箭头函数出现之前,每个新定义的函数都有自己的this值。

  • 构造函数的this指向新的实例对象
  • 严格模式下的函数的this值为undefined
  • 如果函数是作为对象的方法被调用的,则this指向调用它的那个对象
function Person() {
  // 构造函数 Person() 定义的 `this` 就是新实例对象自己
  this.age = 0;
  setInterval(function growUp() {
    // 非严格模式下,growUp() 函数其内部的`this`为全局对象
    // 不同于 Person() 中定义的 `this`
    this.age++;
  }, 1000);
}

var p = new Person();

由于this指向的问题,在面向对象编程中会造成一定的问题,这被证明是非常恼人的事情。在ECMAScript 3/5中,可以使用另一个变量指向this,以达到想要的效果:

function Person() {
  var self = this; // 将'self'变量指向'this'

  self.age = 0;

  setInterval(function growUp() {
    // 回调中的 `self` 变量可以正常指向期望的那个对象了
    self.age++;
  }, 1000);
}

箭头函数总是匿名函数,所以没有自身的作用域。箭头函数会捕获上下文中的this值,做为自己的this值。箭头函数可以很好的解决上面的问题:

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // 'this'正确地指向了 person 对象
  }, 1000);
}

var p = new Person();


严格模式

箭头函数中,this作用域是词法层面的,严格模式中与this的相关的规则都将被忽略,除this外的其它的规则不变。

var f = () => {'use strict'; return this};
f() === window; // ture,全局对象


使用callapply调用

this已经在词法层面完成了绑定,通过callapply方法调用一个函数时,只是传入参数:

var adder = {
  base : 1,
  add : function(a) {
    var f = v => v + this.base;
    return f(a);
  },
  addThruCall: function(a) {
    var f = v => v + this.base;
    var b = {
      base : 2
    }; 
    return f.call(b, a);
  }
};

console.log(adder.add(1));         // 输出 2
console.log(adder.addThruCall(1)); // 仍然输出 2


2.3 arguments词法

箭头函数没有自己的argumentsarguments.lengtharguments[0]等都指向其词法所在作用域的arguments对象。

var arguments = 42;
var arr = () => arguments;

arr(); // 42

function foo() {
  var f = () => arguments[0];
  return f(2);
}

foo(1); // 1