前言
this是一个老生常谈的话题了,自己初学JS时常常迷惑,故在这里做一个小结。
- 函数中的this是什么?
this是函数调用时的执行上下文。
- 函数直接调用,此时函数指向全局(Global 或 Window)
function logThis() {
console.log(this);
}
logThis(); // Global
- 作为对象上的方法,指向调用函数的对象
const video = {
name: "Google",
play() {
console.log(this.name);
},
};
video.play(); // Google
- 在函数的回调中使用
const video = {
name: "Google",
platform: "juejin",
playAd() {
setTimeout(function () {
console.log(this.platform);
}, 100);
},
};
video.playAd(); // undefined
这里我们期望会打印出"juejin",但是回调中函数的调用点(call site)变成了全局,所以打印undefined。
- 解决方案1:使用bind强行绑定执行上下文
const video = {
name: "Google",
platform: "juejin",
playAd() {
setTimeout(function () {
console.log(this.platform);
}.bind(this), 100);
},
};
video.playAd(); // juejin
- 解决方案2: 使用箭头函数
const video = {
name: "Google",
platform: "juejin",
playAd() {
setTimeout(() => {
console.log(this.platform);
}, 100);
},
};
video.playAd(); // juejin
箭头函数本身不定义this关键字,只是向上寻找某一个定义了this的作用域。本例中是playAd函数,然后由video调用,所以此时this指向了video对象。
- 关于对象中的箭头函数
const video = {
name: "Google",
platform: "juejin",
playArrow: () => {
console.log(this.name);
},
};
video.playArrow(); // undefined
这里的原因是对象并不会形成一个作用域,所以箭头函数的this指向了全局。
- class中的函数调用 (实际开发中会遇到,React & Angular)
var name = "Global";
class Video {
constructor() {
this.name = "Facebook";
}
play() {
setTimeout(this.logName, 100);
}
logName() {
console.log(this.name);
}
}
const myVideo = new Video();
myVideo.play(); // Global
此时logName在回调中调用,this的指向了全局。
- 解决方案同样有bind和箭头函数两种,但这里更推荐箭头函数
var name = "Global";
class Video {
constructor() {
this.name = "Facebook";
}
play() {
setTimeout(this.logName, 100);
}
logName = () => {
console.log(this.name);
};
}
const myVideo = new Video();
myVideo.play(); // Facebook