0%

js-箭头函数

箭头函数

箭头函数没有独立的 this、arguments和super 绑定_(en-US),并且不可被用作方法。
箭头函数不能用作构造函数。使用new调用它们会引发TypeError。它们也无法访问new.target关键字。
箭头函数不能在其主体中使用yield,也不能作为生成器函数创建。

1.箭头函数形式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
() => expression

param => expression

(param) => expression

(param1, paramN) => expression

() => {
statements
}

param => {
statements
}

(param1, paramN) => {
statements
}

参数部分支持剩余参数、默认参数和解构赋值,并且始终需要使用括号

剩余参数:剩余参数语法允许我们将一个不定数量的参数表示为一个数组

默认参数:函数默认参数允许在没有值或 undefined 被传入时使用默认形参

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function multiply(a, b = 1) {
return a * b;
}
multiply(5, 2); // 10
multiply(5); // 5
//传入undefined值与其它假值的比较
function test(num = 1) {
console.log(typeof num);
}

test(); // 'number' (num is set to 1)
test(undefined); // 'number' (num is set to 1 too)

// test with other falsy values:
test(""); // 'string' (num is set to '')
test(null); // 'object' (num is set to null)

结构赋值:结构赋值语法是一种 Javascript 表达式。可以将数组中的值或对象的属性取出,赋值给其他变量

1
2
3
4
5
6
7
8
// 剩余参数
(a, b, ...r) => expression

(a = 400, b = 20, c) => expression

//结构赋值
([a, b] = [10, 20]) => expression
({ a, b } = { a: 10, b: 20 }) => expression

2.将匿名函数分解为简单地箭头函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// 传统匿名函数
(function (a) {
return a + 100;
});
// 1. 移除“function”,并将箭头放置于参数和函数体起始大括号之间
(a) => {
return a + 100;
};
// 2. 移除代表函数体的大括号和“return”——返回值是隐含的
(a) => a + 100;
// 3. 移除参数周围的括号
a => a + 100;

// 情况一:
// 传统匿名函数
(function (a, b) {
const chuck = 42;
return a + b + chuck;
});
// 箭头函数
(a, b) => {
const chuck = 42;
return a + b + chuck;
};

// 情况二:
// 传统无参匿名函数
(function () {
return a + b + 100;
});
// 无参箭头函数
() => a + b + 100;

// 情况三:
// 传统函数
function bob(a) {
return a + 100;
}
// 箭头函数
const bob2 = (a) => a + 100;

3.函数体

箭头函数既可以使用表达式体,也可以使用通常的块体。

在表达式体中,只需指定一个表达式,它将成为隐式返回值。在块体中,必须使用显式的 return 语句。

1
2
3
4
5
6
7
const func = (x) => x * x;
// 表达式体语法,隐含返回值

const func2 = (x, y) => {
return x + y;
};
// 块体语法,需要明确返回值

4.箭头函数不能用作方法

箭头函数表达式只能用于非方法函数,因为它们没有自己的 this。

1
2
3
4
5
6
7
8
9
10
11
12
"use strict";

const obj = {
i: 10,
b: () => console.log(this.i, this),
c() {
console.log(this.i, this);
},
};

obj.b(); // 输出 undefined, Window { /* … */ }(或全局对象)
obj.c(); // 输出 10, Object { /* … */ }

由于类体具有this上下文,因此作为类字段的箭头函数会关闭类的this上下文,箭头函数体中的 this将正确指向实例(对于静态字段来说是类本身)。但是,由于它是一个闭包,而不是函数本身的绑定,因此this 的值不会根据执行上下文而改变。

1
2
3
4
5
6
7
8
9
10
11
class C {
a = 1;
autoBoundMethod = () => {
console.log(this.a);
};
}
const c = new C();
c.autoBoundMethod(); // 1
const { autoBoundMethod } = c;
autoBoundMethod(); // 1
// 如果这是普通方法,此时应该是 undefined

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

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

5.不能用作构造函数

箭头函数不能用作构造函数,当使用new调用时会出错。它们也没有prototype属性。

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

6.不能用作生成器

箭头函数的主体中不能使用yield关键字((除非在箭头函数进一步嵌套的生成器函数中使用)。

7.箭头前换行(箭头函数的参数和箭头之间不能换行。)

为便于格式化,可在箭头后换行,或在函数体周围使用括号/花括号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;

8.箭头函数的优先级

虽然箭头函数中的箭头不是运算符,但与普通函数相比,箭头函数具有特殊的解析规则,与运算符优先级的交互方式不同。

由于=>的优先级低于大多数运算符,因此需要使用括号来避免callback ll ()被解析为箭头函数的参数列表。

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