六维教程

ES6 箭头函数

箭头函数是 ES6 里出现频率最高的语法之一,写法从 function 变成了 =>

很多人以为它只是”函数简写”,但它还有一个根本性变化this 的指向。

这篇讲清楚两件事——怎么写、以及 this 到底有什么不同。

箭头函数怎么写

先看最直观的对比:

// ES5:function 关键字
function add(a, b) {
  return a + b;
}

// ES6:箭头函数
const add = (a, b) => a + b;

三种写法规则

箭头函数有两种”形态”——表达式形态和声明形态,先看最基本的:

// ① 完整写法:有参数、函数体多行、需要 return
const add = (a, b) => {
  return a + b;
};

// ② 单表达式写法:函数体只有一行,可以不加 {} 和 return(自动返回)
const add2 = (a, b) => a + b;

// ③ 只有一个参数时,连括号都可以省
const double = x => x * 2;

三个规律:

情况 写法
只有一个参数 括号可省略:x => ...
没有参数 括号不能省:() => ...
函数体只有一行 省略 {}return,自动返回该值

自动返回那个功能很常用。但你保留 {} 时,就必须手动写 return,否则返回 undefined

箭头函数不是”到处都能用”

箭头函数有两条硬性规则:

  1. 不能做构造函数new 是”创建对象实例”的关键字(后面 class 一章也会用到),箭头函数不能配合 new 使用(会报错)。
  2. 没有 arguments 对象arguments 是普通函数自带的”当前实参集合”对象。箭头函数内部拿不到它(需要的话可以用 rest 参数代替,后面函数扩展一章讲)。

这两条先记住结论即可,等用到时自然就理解了。

关键区别:this 指向

这是箭头函数最难、也最重要的内容。

普通函数的 this:谁调用,指向谁

普通函数的 this调用时确定的——谁调用它,this 就是谁:

// 示例
function getName() {
  console.log(this); // 取决于调用方式
}

getName();              // 浏览器里 this 是 window
const obj = { getName };
obj.getName();          // 由 obj 调用,this 就是 obj

箭头函数的 this:定义时确定,不随调用变化

箭头函数没有自己的 this,它用的是定义时所处外层作用域的 this,之后不管怎么调用都不变。这是它和普通函数最大的区别。

看一个新手最容易踩的坑——定时器里丢失 this

// ES5 写法:this 会丢(问题代码)
const user = {
  name: '小明',
  show() {
    setTimeout(function () {
      console.log(this.name); // 报错/undefined
    }, 100);
  }
};

上面 setTimeout 里的普通函数,它调用时由浏览器执行,this 变成了全局对象,访问不到 user.name

换成箭头函数,问题消失:

// ES6 写法:箭头函数,this 指向外层 user
const user = {
  name: '小明',
  show() {
    setTimeout(() => {
      console.log(this.name); // 小明
    }, 100);
  }
};

因为箭头函数用的 this定义时外层作用域的 this——也就是 show 方法里的 this,即 user。定时器触发时,this 依然是 user

一句话记忆:

普通函数:this 看”谁调用”;箭头函数:this 看”在哪定义”。

什么时候用箭头函数

场景 选择
写数组方法回调(mapfilter 箭头函数,简洁
定时器、事件回调里需要访问外层 this 箭头函数
定义对象的方法(需要 this 指向对象) 普通方法
需要动态 this(如事件解绑、构造函数) 普通函数
上一篇
ES6 let 和 const
下一篇
ES6 函数扩展