最近翻译了一篇关于 this 的文章,不少人评价不错,可是原文没有讲到箭头函数的 this
,因此我来补充一篇文章来专门讲解。浏览器
箭头函数是 ES6 添加的新语法,基础知识就很少介绍了,下面咱们来说一讲箭头函数的 this
怎么指向。bash
在以往的函数中,this
有各类各样的指向(隐式绑定,显示绑定,new 绑定, window 绑定......),虽然灵活方便,但因为不能在定义函数时而直到实际调用时才能知道 this
指向,很容易给开发者带来诸多困扰。闭包
假如咱们有下面这段代码(本文代码都是在浏览器下运行),app
function User() {
this.name = 'John';
setTimeout(function greet() {
console.log(`Hello, my name is ${this.name}`); // Hello, my name is
console.log(this); // window
}, 1000);
}
const user = new User();
复制代码
greet
里的 this
能够由上一篇文章的四个规则判断出来。对,由于没有显示绑定、隐式绑定或 new
绑定、因此直接得出结论 this
指向 window
。但实际上咱们想把 this
指向 user
对象!函数
之前是怎么解决的呢?看下面的代码:post
1. 使用闭包ui
function User() {
const self = this;
this.name = 'John';
setTimeout(function greet() {
console.log(`Hello, my name is ${self.name}`); // Hello, my name is John
console.log(self); // User {name: "John"}
}, 1000);
}
const user = new User();
复制代码
2. 使用显示绑定 — bind
this
function User() {
this.name = 'John';
setTimeout(function greet() {
console.log(`Hello, my name is ${this.name}`); // Hello, my name is John
console.log(this); // User {name: "John"}
}.bind(this)(), 1000);
}
const user = new User();
复制代码
3. 利用 setTimeout
的能够传更多参数的特性spa
其实第三种和第一种比较像,都用到了闭包。翻译
function User() {
this.name = 'John';
setTimeout(function greet(self) {
console.log(`Hello, my name is ${self.name}`); // Hello, my name is John
console.log(self); // User {name: "John"}
}, 1000, this);
}
const user = new User();
复制代码
三种方法均可以解决问题,可是都要额外写冗余的代码来指定 this
。
如今,箭头函数(Arrow Function)正是 ES6 引入来解决这个问题的,它能够轻松地让 greet
函数保持 this
指向 user
对象。
下面是箭头函数版本:
function User() {
this.name = 'John';
setTimeout(() => {
console.log(`Hello, my name is ${this.name}`); // Hello, my name is John
console.log(this); // User {name: "John"}
}, 1000);
}
const user = new User();
复制代码
完美,直接把普通函数改为箭头函数就能解决问题。
箭头函数在本身的做用域内不绑定 this
,即没有本身的 this
,若是要使用 this
,就会指向定义时所在的做用域的 this
值。在上面的代码中即指向 User
函数的 this
,而 User 函数经过 new
绑定,因此 this
实际指向 user
对象。
若是上述代码在严格模式下运行会有影响吗?
function User() {
this.name = 'John';
setTimeout(() => {
'use strict'
console.log(`Hello, my name is ${this.name}`); // Hello, my name is John
console.log(this); // User {name: "John"}
}, 1000);
}
const user = new User();
复制代码
答案是没有影响。由于箭头函数没有本身的 this
,它的 this
来自于 User
的 this
,只要 User
的 this
不变,箭头函数的 this
也保持不变。
那么使用 bind
,call
或者 apply
呢?
function User() {
this.name = 'John';
setTimeout((() => {
console.log(`Hello, my name is ${this.name}`); // Hello, my name is John
console.log(this); // User {name: "John"}
}).bind('no body'), 1000);
}
const user = new User();
复制代码
答案仍是没有影响。由于箭头函数没有本身的 this
,使用 bind
,call
或者 apply
时,箭头函数会自动忽略掉 bind
的第一个参数,即 thisArg
。
总结:箭头函数在本身的做用域内没有本身的 this
,若是要使用 this
,就会指向定义时所在的做用域的 this
值。
欢迎在下方评论交流哦!