1
0
mirror of https://github.com/ruanyf/es6tutorial.git synced 2025-05-24 18:32:22 +00:00

docs(function): fixed 箭头函数的this #1050

This commit is contained in:
ruanyf 2021-05-12 01:07:14 +08:00
parent 0163114de4
commit 71af30def1

View File

@ -708,15 +708,15 @@ headAndTail(1, 2, 3, 4, 5)
箭头函数有几个使用注意点。
1函数体内的`this`对象,就是定义时所在的对象,而不是使用时所在的对象
1箭头函数没有自己的`this`对象(详见下文)
2不可以当作构造函数也就是说不可以使用`new`命令,否则会抛出一个错误。
2不可以当作构造函数也就是说不可以对箭头函数使用`new`命令,否则会抛出一个错误。
3不可以使用`arguments`对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
4不可以使用`yield`命令,因此箭头函数不能用作 Generator 函数。
上面四点中,第一点尤其值得注意。`this`对象的指向是可变的,但是在箭头函数中,它是固定的。
上面四点中,最重要的是第一点。对于普通函数来说,内部的`this`代表函数运行时所在的对象,但是这一点对箭头函数不成立。它没有自己的`this`对象,内部的`this`就是一个普通变量,指向定义时上层函数所在的对象。也就是说,箭头函数内部的`this`指向是固定的,相比之下,普通函数的`this`指向是可变的。
```javascript
function foo() {
@ -733,7 +733,7 @@ foo.call({ id: 42 });
上面代码中,`setTimeout()`的参数是一个箭头函数,这个箭头函数的定义生效是在`foo`函数生成时,而它的真正执行要等到 100 毫秒后。如果是普通函数,执行时`this`应该指向全局对象`window`,这时应该输出`21`。但是,箭头函数导致`this`总是指向函数定义生效时所在的对象(本例是`{id: 42}`),所以打印出来的是`42`
箭头函数可以让`setTimeout`里面的`this`,绑定定义时所在的作用域,而不是指向运行时所在的作用域。下面是另一个例子
下面例子是回调函数分别为箭头函数和普通函数,对比它们内部的`this`指向
```javascript
function Timer() {
@ -757,7 +757,7 @@ setTimeout(() => console.log('s2: ', timer.s2), 3100);
上面代码中,`Timer`函数内部设置了两个定时器,分别使用了箭头函数和普通函数。前者的`this`绑定定义时所在的作用域(即`Timer`函数),后者的`this`指向运行时所在的作用域即全局对象。所以3100 毫秒之后,`timer.s1`被更新了 3 次,而`timer.s2`一次都没更新。
箭头函数可以让`this`指向固定化这种特性很有利于封装回调函数。下面是一个例子DOM 事件的回调函数封装在一个对象里面。
箭头函数实际上可以让`this`指向固定化,绑定`this`使得它不再可变这种特性很有利于封装回调函数。下面是一个例子DOM 事件的回调函数封装在一个对象里面。
```javascript
var handler = {
@ -774,11 +774,11 @@ var handler = {
};
```
上面代码的`init`方法中,使用了箭头函数,这导致这个箭头函数里面的`this`,总是指向`handler`对象。否则,回调函数运行时,`this.doSomething`这一行会报错,因为此时`this`指向`document`对象。
上面代码的`init()`方法中,使用了箭头函数,这导致这个箭头函数里面的`this`,总是指向`handler`对象。如果回调函数是普通函数,那么运行`this.doSomething()`这一行会报错,因为此时`this`指向`document`对象。
`this`指向的固定化,并不是因为箭头函数内部有绑定`this`的机制,实际原因是箭头函数根本没有自己的`this`,导致内部的`this`就是外层代码块的`this`。正是因为它没有`this`,所以也就不能用作构造函数。
总之,箭头函数根本没有自己的`this`,导致内部的`this`就是外层代码块的`this`。正是因为它没有`this`,所以也就不能用作构造函数。
所以,箭头函数转成 ES5 的代码如下
下面是 Babel 转箭头函数产生的 ES5 代码,就能清楚地说明`this`的指向
```javascript
// ES6
@ -800,7 +800,7 @@ function foo() {
上面代码中,转换后的 ES5 版本清楚地说明了,箭头函数里面根本没有自己的`this`,而是引用外层的`this`
请问下面的代码之中有几个`this`
请问下面的代码之中`this`的指向有几个
```javascript
function foo() {
@ -820,7 +820,7 @@ var t2 = f().call({id: 3})(); // id: 1
var t3 = f()().call({id: 4}); // id: 1
```
上面代码之中,只有一个`this`,就是函数`foo``this`,所以`t1``t2``t3`都输出同样的结果。因为所有的内层函数都是箭头函数,都没有自己的`this`,它们的`this`其实都是最外层`foo`函数的`this`
答案是`this`的指向只有一个,就是函数`foo``this`,这是因为所有的内层函数都是箭头函数,都没有自己的`this`,它们的`this`其实都是最外层`foo`函数的`this`所以不管怎么嵌套,`t1``t2``t3`都输出同样的结果。如果这个例子的所有内层函数都写成普通函数,那么每个函数的`this`都指向运行时所在的不同对象。
除了`this`,以下三个变量在箭头函数之中也是不存在的,指向外层函数的对应变量:`arguments``super``new.target`