JavaScript 的函数 (函数声明式) 中, this 指向的是运行时的作用域, 如果没有对象调用函数, 则 this 指向 global/Windows, 但是在箭头函数中, this 的指向是固化的, 如下面代码所示:
- function Timer() {
- this.s1 = 0
- this.s2 = 0
- setInterval(() => {
- this.s1++
- }, 1000)
- setInterval(function () {
- // console.log(this)
- this.s2++
- }, 1000)
- }
- var timer = new Timer()
- setTimeout(() => console.log('s1:', timer.s1), 3100) // 3
- setTimeout(() => console.log('s1:', timer.s2), 3100) // 0
那么怎样理解输出的结果呢? 其实只需要搞清楚在第 4 行和第 7 行中两个函数 this 的指向就行了.
在第 4 行中, 使用的是箭头函数, 箭头函数 this 绑定定义时所在的作用域(即 Timer 函数), 则该 this 指向的是 Timer 函数中的对象
在第 7 行中, 使用的是函数声明式, 此时 this 指向运行时的作用域, 即全局对象, 操作的自然就不是 Timer 函数中的 s2 了
- function Timer() {
- this.s1 = 0
- this.s2 = 0
- setInterval(() => {
- this.s1++
- }, 1000)
- setInterval(func.bind(this), 1000)
- function func() {
- this.s2++
- }
- }
- var timer = new Timer()
- setTimeout(() => console.log('s1:', timer.s1), 3100) // 3
- setTimeout(() => console.log('s1:', timer.s2), 3100) // 3
改代码是上面代码的更改版, 在第 7 行中, func 还是函数声明式, 但是对该函数的 this 使用了 bind 进行了绑定, 所以该函数的作用域从全局作用域更改成为了 Timer 函数作用域
总结:
1. 箭头函数可以让 this 指向固化, 但是 this 指向固化并不是因为箭头函数内部有绑定的 this 机制, 实际原因是箭头函数根本没有自己的 this, 导致内部的 this 就是外层代码块的 this.(使用作用链域思想理解)正是由于箭头函数没有 this, 所以不能用作构造函数.
2. arguments,super 和 new.target 在箭头函数中是不存在(可以使用, 只不过这三个变量的作用域指向的是外层函数)
3. 由于箭头函数中没有自己的 this, 所以箭头函数不能使用 call(),apply(),bind()这三个方法去改变 this 的指向.
引用地址:
1. 《ES6 标准入门》,118 页~ 121 页.
2. 一篇写 JS 函数 (声明式) 的 this 的博客, 写的非常棒: https://www.cnblogs.com/xiangxiao/p/6822997.html
来源: https://www.cnblogs.com/oulae/p/11072265.html