首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Arrow functions

箭头函数表达式的语法比函数表达式更短,并且不绑定自己的thisargumentssuper或?new.target。这些函数表达式最适合用于非方法函数,并且它们不能用作构造函数。

语法

代码语言:javascript
复制
基础语法

代码语言:javascript
复制
(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
// equivalent to: (param1, param2, …, paramN) => { return expression; }

// Parentheses are optional when there's only one parameter name:
(singleParam) => { statements }
singleParam => { statements }

// A function with no parameters should be written with a pair of parentheses.
() => { statements }

高级语法

代码语言:javascript
复制
// Parenthesize the body of function to return an object literal expression:
params => ({foo: bar})

// Rest parameters and default parameters are supported
(param1, param2, ...rest) => { statements }
(param1 = defaultValue1, param2, …, paramN = defaultValueN) => { statements }

// Destructuring within the parameter list is also supported
let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f();  
// 6

描述

引入箭头函数有两个方面的作用:更简短的函数并且不绑定this

更短的函数

代码语言:javascript
复制
var materials = [
  'Hydrogen',
  'Helium',
  'Lithium',
  'Beryllium'
];

materials.map(function(material) { 
  return material.length; 
}); // [8, 6, 7, 9]

materials.map((material) => {
  return material.length;
}); // [8, 6, 7, 9]

materials.map(material => material.length); // [8, 6, 7, 9]

不绑定this

在箭头函数出现之前,每个新定义的函数都有它自己的?this值(在构造函数的情况下是一个新对象,在严格模式的函数调用中为 undefined,如果该函数被称为“对象方法”则为基础对象等)。This被证明是令人厌烦的面向对象风格的编程。

代码语言:javascript
复制
function Person() {
  // The Person() constructor defines `this` as an instance of itself.
  this.age = 0;

  setInterval(function growUp() {
    // In non-strict mode, the growUp() function defines `this` 
    // as the global object, which is different from the `this`
    // defined by the Person() constructor.
    this.age++;
  }, 1000);
}

var p = new Person();

在ECMAScript 3/5中,通过将this值分配给封闭的变量,可以解决this问题。

代码语言:javascript
复制
function Person() {
  var that = this;
  that.age = 0;

  setInterval(function growUp() {
    // The callback refers to the `that` variable of which
    // the value is the expected object.
    that.age++;
  }, 1000);
}

或者,可以创建绑定函数,以便将预先分配的this值传递到绑定的目标函数(上述示例中的growUp()函数)。

箭头函数不会创建自己的this;它使用封闭执行上下文的this值。因此,在下面的代码中,传递给setInterval的函数内的this与封闭函数中的this值相同:

代码语言:javascript
复制
function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| properly refers to the person object
  }, 1000);
}

var p = new Person();

与严格模式的关系

鉴于?this?是词法层面上的,严格模式中与?this?相关的规则都将被忽略。

代码语言:javascript
复制
var f = () => { 'use strict'; return this; };
f() === window; // or the global object

严格模式的其他规则依然不变.

通过 call 或?apply 调用

由于?this已经在词法层面完成了绑定,通过?call()?或apply()?方法调用一个函数时,只是传入了参数而已,对?this?并没有什么影响:

代码语言:javascript
复制
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));         // This would log to 2
console.log(adder.addThruCall(1)); // This would log to 2 still

不绑定arguments

箭头函数不绑定Arguments 对象。因此,在本示例中,参数只是在封闭范围内引用相同的名称:

代码语言:javascript
复制
var arguments = 42;
var arr = () => arguments;

arr(); // 42

function foo() {
  var f = (i) => arguments[0] + i; // foo's implicit arguments binding
  return f(2);
}

foo(1); // 3

在大多数情况下,使用剩余参数是使用arguments对象的好选择。

代码语言:javascript
复制
function foo() { 
  var f = (...args) => args[0]; 
  return f(2); 
}

foo(); // 2

像方法一样使用箭头函数

如上所述,箭头函数表达式对非方法函数是最合适的。让我们看看当我们试着把它们作为方法时发生了什么。

代码语言:javascript
复制
'use strict';
var obj = {
  i: 10,
  b: () => console.log(this.i, this),
  c: function() {
    console.log(this.i, this);
  }
}
obj.b(); // prints undefined, Window {...} (or the global object)
obj.c(); // prints 10, Object {...}

箭头函数没有定义this绑定。另一个涉及Object.defineProperty()的示例:

代码语言:javascript
复制
'use strict';
var obj = {
  a: 10
};

Object.defineProperty(obj, 'b', {
  get: () => {
    console.log(this.a, typeof this.a, this);
    return this.a + 10; // represents global object 'Window', therefore 'this.a' returns 'undefined'
  }
});

使用?new?操作符

箭头函数不能用作构造器,和new一起用会抛出错误。

代码语言:javascript
复制
var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor

使用prototype属性

箭头函数没有prototype属性。

代码语言:javascript
复制
var Foo = () => {};
console.log(Foo.prototype); // undefined

使用?yield?关键字

yield?关键字通常不能在箭头函数中使用(除非是嵌套在允许使用的函数内)。因此,箭头函数不能用作生成器。

函数体

箭头函数可以有一个“简写体”或常见的“块体”。

在一个简写体中,只需要一个表达式,并附加一个隐式的返回值。在块体中,必须使用明确的return语句。

代码语言:javascript
复制
var func = x => x * x;                  
// concise syntax, implied "return"

var func = (x, y) => { return x + y; }; 
// with block body, explicit "return" needed

返回对象字面量

记住用params => {object:literal}这种简单的语法返回对象字面量是行不通的。

代码语言:javascript
复制
var func = () => { foo: 1 };               
// Calling func() returns undefined!

var func = () => { foo: function() {} };   
// SyntaxError: function statement requires a name

这是因为花括号({})里面的代码被解析为一系列语句(即?foo?被认为是一个标签,而非对象字面量的组成部分)。

所以,记得用圆括号把对象字面量包起来:

代码语言:javascript
复制
var func = () => ({foo: 1});

换行

箭头函数在参数和箭头之间不能换行。

代码语言:javascript
复制
var func = ()
           => 1; 
// SyntaxError: expected expression, got '=>'

解析顺序

虽然箭头函数中的箭头不是运算符,但箭头函数具有与常规函数不同的特殊运算符优先级解析规则。

代码语言:javascript
复制
let callback;

callback = callback || function() {}; // ok

callback = callback || () => {};      
// SyntaxError: invalid arrow-function arguments

callback = callback || (() => {});    // ok

更多示例

代码语言:javascript
复制
// An empty arrow function returns undefined
let empty = () => {};

(() => 'foobar')(); 
// Returns "foobar"
// (this is an Immediately Invoked Function Expression 
// see 'IIFE' in glossary)

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

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

// Easy array filtering, mapping, ...

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]

// More concise promise chains
promise.then(a => {
  // ...
}).then(b => {
  // ...
});

// Parameterless arrow functions that are visually easier to parse
setTimeout( () => {
  console.log('I happen sooner');
  setTimeout( () => {
    // deeper code
    console.log('I happen later');
  }, 1);
}, 1);  

规范

Specification

Status

Comment

ECMAScript 2015 (6th Edition, ECMA-262)The definition of 'Arrow Function Definitions' in that specification.

Standard

Initial definition.

ECMAScript Latest Draft (ECMA-262)The definition of 'Arrow Function Definitions' in that specification.

Living Standard

?

浏览器兼容性

Feature

Chrome

Edge

Firefox (Gecko)

Internet Explorer

Opera

Safari

Basic support

45.0

(Yes)

22.0 (22.0)

No support

32

10.0

Trailing comma in parameters

?

?

52.0 (52.0)

?

?

?

Feature

Android

Android Webview

Edge

Firefox Mobile (Gecko)

IE Mobile

Opera Mobile

Safari Mobile

Chrome for Android

Basic support

No support

45.0

(Yes)

22.0 (22.0)

No support

No support

10.0

45.0

Trailing comma in parameters

?

?

?

52.0 (52.0)

?

?

?

?

Firefox特定的笔记

  • Firefox中的箭头函数的初始实现使得它们自动严格。这已经改变为Firefox 24。采用"use strict";它现在需要的。
  • 箭头函数在语义上与Firefox 3中添加的非标准表达式闭包不同(细节:JavaScript 1.8),是由于表达式闭包不会在this词法上绑定。
  • Firefox 39之前,在箭头函数参数之后不正确地允许行结束符(\n)。这已经被修正,以符合ES2015规范和像() \n => {}现在将在这个和以后的版本的代码中抛出一个SyntaxError

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com