前言
前面写过关于JavaScript的this指向的基础文章,链接:juejin.cn/post/751796…
今天我们继续来讲讲闭包的应用场景之一:绑定上下文。
实例
来看看这个经典案例:
const person = {
name: "Alice",
sayHello: function () {
setTimeout(function () {
console.log("Hello, " + this.name);
}, 1000);
}
}
person.sayHello(); // 输出:
会输出什么呢?
Hello,Alice?
no!
会输出 Hello,undefined
这里涉及到
this丢失问题,setTimeout定时器是个全局函数,所以执行的调用者是window,而它没有name属性,故为undefined
如何解决this丢失问题?
法一:that = this
const person = {
name: "Alice",
sayHello: function () {
const that = this; // 保存this的引用
setTimeout(function () {
console.log("Hello, " + that.name);
}, 1000);
}
}
person.sayHello(); // 输出:Hello, Alice
这里在定时器前利用闭包的特性,用that保存了this,就可以正确引用name
法二:箭头函数
我们都知道箭头函数没有this,它会沿用词法作用域上层函数的this,我们可以借用它这个特性,来解决这个丢失问题。
const person = {
name: "Alice",
sayHello: function () {
// this丢失
setTimeout(()=> { // 改成箭头函数,他没有自己的this,会向上查找作用域链,找到this指向person对象
console.log("Hello, " + this.name);
}, 1000);
}
}
person.sayHello(); // 输出:Hello, Alice
这里的箭头函数的
this来自沿用词法作用域上层函数(sayHello)
法三:bind()
const person = {
name: "Alice",
sayHello: function () {
// this丢失
setTimeout(function () {
console.log("Hello, " + this.name); // 这里的this指向window对象,因为setTimeout是一个全局函数
}.bind(this), 1000);
}
}
person.sayHello(); // 输出:Hello, Alice
函数是一等对象,当然可以调用
bind()来改变this指向
.bind(this)的作用是:创建一个新的函数,无论它在哪里被调用,它的this都永远指向当前绑定的对象。
在这里,外层函数中 this 是 person,所以 .bind(this) 把 this 绑定为了 person。
结尾
闭包在面试中是个必考点,对它深入学习是很有必要的,一起加油吧!