专注Java教育14年 全国咨询/投诉热线:444-1124-454
赢咖4LOGO图
始于2009,口口相传的Java黄埔军校
首页 hot资讯 ES6的箭头函数表达式

ES6的箭头函数表达式

更新时间:2022-11-17 09:48:41 来源:赢咖4 浏览254次

箭函数表达式是一个紧凑的替代传统的函数表达式,在使用一些语义差异和刻意的限制:

箭头没有自己的绑定功能,参数,或超,不应使用方法。

箭头功能不能用作构造函数。用新扔一个TypeError调用。他们也没有新的。目标关键词。

箭头功能不能使用收益率在他们的身体,不能创建生成器的功能。

试一试

const materials = [
  'Hydrogen',
  'Helium',
  'Lithium',
  'Beryllium'
];
console.log(materials.map(material => material.length));
// expected output: Array [8, 6, 7, 9]

语法

param => expression
(param) => expression
(param1, paramN) => expression
param => {
  statements
}
(param1, paramN) => {
  statements
}

其他参数,默认参数,支持和解构params,总是需要括号:

(a, b, ...r) => expression
(a = 400, b = 20, c) => expression
([a, b] = [10, 20]) => expression
({ a, b } = { a: 10, b: 20 }) => expression

箭头功能可以异步与异步关键字前缀表达式。

async param => expression
async (param1, param2, ...paramN) => {
  statements
}

描述

让我们分解传统的匿名函数最简单箭头功能逐步下降。沿途每一步都是一个有效的箭头功能。

// Traditional anonymous function
(function (a) {
  return a + 100;
});
// 1. Remove the word "function" and place arrow between the argument and opening body bracket
(a) => {
  return a + 100;
};
// 2. Remove the body braces and word "return" — the return is implied.
(a) => a + 100;
// 3. Remove the parameter parentheses
a => a + 100;

在上面的示例中,括号在参数和函数体周围的括号可以省略。然而,他们只能省略了在某些情况下。

括号只能省略如果函数有一个简单的参数。如果有多个参数,没有参数,或违约,变性,或其它参数,参数列表的括号是必需的。

// Traditional anonymous function
(function (a, b) {
  return a + b + 100;
});
// Arrow function
(a, b) => a + b + 100;
const a = 4;
const b = 2;
// Traditional anonymous function (no parameters)
(function() {
  return a + b + 100;
});
// Arrow function (no arguments)
() => a + b + 100;

括号只能省略如果函数直接返回一个表达式。如果身体有额外的行处理,括号是必需的——所以返回关键字。箭头函数不能猜测或当您想要返回。

// Traditional anonymous function
(function (a, b) {
  const chuck = 42;
  return a + b + chuck;
});
// Arrow function
(a, b) => {
  const chuck = 42;
  return a + b + chuck;
};

箭头总是匿名函数。如果箭头函数需要调用本身,而不是使用一个命名函数表达式。您还可以将箭头功能分配给一个变量,所以它有一个名字。

// Traditional Function
function bob(a) {
  return a + 100;
}
// Arrow Function
const bob2 = (a) => a + 100;

函数体

箭头功能可以有一个简洁的身体或通常的块体。

在一个简洁的身体,只有一个表达式指定,这成为了隐式返回值。在一块的身体,你必须使用一个显式的返回语句。

const func = (x) => x * x;
// concise body syntax, implied "return"
const func2 = (x, y) => {
  return x + y;
};
// with block body, explicit "return" needed

返回对象文字使用简洁的身体语法(params) = >{对象:文字}并不像预期的那样工作。

const func = () => { foo: 1 };
// Calling func() returns undefined!
const func2 = () => { foo: function () {} };
// SyntaxError: function statement requires a name
const func3 = () => { foo() {} };
// SyntaxError: Unexpected token '{'

这是因为JavaScript只能看到箭头功能简洁的身体如果箭头不是一个左括号后的令牌,所以在括号({})中的代码解析语句序列,在foo是一个标签,而不是对象字面量的关键。

为了解决这个问题,将对象文字括号内:

const func = () => ({ foo: 1 });

不能使用方法

箭头函数表达式只能用于non-method因为他们没有自己的这个功能。让我们看看会发生什么当我们试图使用它们作为方法:

"use strict";
const obj = {
  i: 10,
  b: () => console.log(this.i, this),
  c() {
    console.log(this.i, this);
  },
};
obj.b(); // logs undefined, Window { /* … */ } (or the global object)
obj.c(); // logs 10, Object { /* … */ }

另一个例子涉及Object.defineProperty ():

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

因为类的身体有这种背景下,箭头函数作为类字段封盖类的这种背景下,和这个箭头函数体内将正确地指向实例(或类本身,对于静态字段)。然而,因为它是一个闭包,而不是函数的绑定,这个不会改变的值基于执行上下文。

class C {
  a = 1;
  autoBoundMethod = () => {
    console.log(this.a);
  }
}
const c = new C();
c.autoBoundMethod(); // 1
const { autoBoundMethod } = c;
autoBoundMethod(); // 1
// If it were a normal method, it should be undefined in this case

箭头功能属性,常常被认为是“auto-bound方法”,因为相当于正常的方法是:

class C {
  a = 1;
  constructor() {
    this.method = this.method.bind(this);
  }
  method() {
    console.log(this.a);
  }
}

出于类似的原因,叫(),(),和绑定()方法不呼吁箭头功能时非常有用,因为箭函数建立基于箭头函数内定义范围,而不改变这个值基于函数被调用。

没有绑定的参数

箭头函数没有自己的参数对象。因此,在这个例子中,参数是指封闭范围的参数:

const arguments = [1, 2, 3];
const arr = () => arguments[0];
arr(); // 1
function foo(n) {
  const f = () => arguments[0] + n; // foo's implicit arguments binding. arguments[0] is n
  return f();
}
foo(3); // 3 + 3 = 6

在大多数情况下,使用其他参数使用一个参数对象是一个不错的选择。

function foo(n) {
  const f = (...args) => args[0] + n;
  return f(10);
}
foo(1); // 11

不能用作构造函数

箭头功能不能使用构造函数和被称为新时将抛出一个错误。他们还没有一个原型属性。

const Foo = () => {};
const foo = new Foo(); // TypeError: Foo is not a constructor
console.log("prototype" in Foo); // false

不能作为发电机使用

收益率的关键字不能用于箭功能的身体(除非生成器中使用函数进一步嵌套在箭头功能)。因此,不能作为发电机使用箭头功能。

换行符之前箭

箭函数之间不能包含换行符参数和箭头。

const func = (a, b, c)
  => 1;
// SyntaxError: Unexpected token '=>'

为目的的格式,你可以把箭头后换行符或使用括号/括号在函数体,如下所示。你也可以把参数之间换行符。

const func = (a, b, c) =>
  1;
const func2 = (a, b, c) => (
  1
);
const func3 = (a, b, c) => {
  return 1;
};
const func4 = (
  a,
  b,
  c,
) => 1;

优先级的箭头

虽然箭在箭函数不是一个运营商,箭头功能有特殊交互的解析规则不同的运算符优先级比常规功能。

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

因为= >有一个较低的优先级比大多数运营商,括号是必要的,以避免回调| |()被解析为箭头函数的参数列表。

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

例子

使用箭头函数

// An empty arrow function returns undefined
const empty = () => {};
(() => 'foobar')();
// Returns "foobar"
// (this is an Immediately Invoked Function Expression)
const simple = (a) => a > 15 ? 15 : a;
simple(16); // 15
simple(10); // 10
const max = (a, b) => a > b ? a : b;
// Easy array filtering, mapping, etc.
const arr = [5, 6, 13, 0, 1, 18, 23];
const sum = arr.reduce((a, b) => a + b);
// 66
const even = arr.filter((v) => v % 2 === 0);
// [6, 0, 18]
const 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);

使用电话、绑定和适用

()的调用,应用()和绑定()方法与传统功能正常工作,因为我们建立的范围为每个方法:

const obj = {
  num: 100,
};
// Setting "num" on globalThis to show how it is NOT used.
globalThis.num = 42;
// A simple traditional function to operate on "this"
const add = function (a, b, c) {
  return this.num + a + b + c;
};
console.log(add.call(obj, 1, 2, 3)); // 106
console.log(add.apply(obj, [1, 2, 3])); // 106
const boundAdd = add.bind(obj);
console.log(boundAdd(1, 2, 3)); // 106

使用电话、绑定和适用

()的调用,应用()和绑定()方法与传统功能正常工作,因为我们建立的范围为每个方法:

const obj = {
  num: 100,
};
// Setting "num" on globalThis to show how it gets picked up.
globalThis.num = 42;
// Arrow function
const add = (a, b, c) => this.num + a + b + c;
console.log(add.call(obj, 1, 2, 3)); // 48
console.log(add.apply(obj, [1, 2, 3])); // 48
const boundAdd = add.bind(obj);
console.log(boundAdd(1, 2, 3)); // 48

也许使用箭头函数的最大的好处是与setTimeout()和EventTarget.prototype.addEventListener等方法(),通常需要关闭,叫(),(),或绑定(),以确保函数执行在适当的范围。

与传统的函数表达式,这样的代码并不像预期的那样工作:

const obj = {
  count: 10,
  doSomethingLater() {
    setTimeout(function () { // the function executes on the window scope
      this.count++;
      console.log(this.count);
    }, 300);
  },
};
obj.doSomethingLater(); // logs "NaN", because the property "count" is not in the window scope.

箭头功能,这个范围是更容易保存:

const obj = {
  count: 10,
  doSomethingLater() {
    // The method syntax binds "this" to the "obj" context.
    setTimeout(() => {
      // Since the arrow function doesn't have its own binding and
      // setTimeout (as a function call) doesn't create a binding
      // itself, the "obj" context of the outer method is used.
      this.count++;
      console.log(this.count);
    }, 300);
  },
};
obj.doSomethingLater(); // logs 11

 

提交申请后,顾问老师会电话与您沟通安排学习

免费课程推荐 >>
技术文档推荐 >>