class MyClass {
constructor() {
this.value = "Class value";
}
regularFunction() {
console.log("Regular function: ", this.value);
}
arrowFunction = () => {
console.log("Arrow function: ", this.value);
}
}
const obj = {
value: "Object value",
method: function (callback) {
callback();
}
};
const instance = new MyClass();
// 问题1:请预测以下四个console.log语句的输出。
instance.regularFunction();
instance.arrowFunction();
obj.method(instance.regularFunction);
obj.method(instance.arrowFunction);
// 问题2:请解释为什么每个输出是这样的,并解释this的指向。
// 问题3:现在假设我们有一个异步操作如下:
setTimeout(instance.regularFunction, 1000);
// 请解释这段代码中的this指向,以及为什么是这样的指向。如果需要保持this指向实例,应该如何修改代码?
这道题目包含以下几个要点:
- 类中的普通方法与箭头函数的
this
指向差异。 - 函数作为参数传递时
this
指向的变化。 - 异步函数如
setTimeout
中this
指向的问题。
答案
// 问题1:请预测以下四个console.log语句的输出。
instance.regularFunction(); // 输出:"Regular function: Class value"
instance.arrowFunction(); // 输出:"Arrow function: Class value"
obj.method(instance.regularFunction); // 输出:"Regular function: Object value"
obj.method(instance.arrowFunction); // 输出:"Arrow function: Class value"
问题2:请解释为什么每个输出是这样的,并解释this的指向。
instance.regularFunction()
:在这个调用中,this
指向实例instance
,因为regularFunction
是作为instance
的一个方法被调用的。所以,输出的值是"Regular function: Class value"
。instance.arrowFunction()
:箭头函数不绑定自己的this
,而是从创建时的上下文中继承this
。在这个例子中,箭头函数是在MyClass
的构造函数中创建的,因此this
指向实例instance
。所以,输出的值是"Arrow function: Class value"
。obj.method(instance.regularFunction)
:当instance.regularFunction
作为回调函数传递给obj.method
时,this
的指向在调用时决定,即this
将指向obj
。所以,输出的值是"Regular function: Object value"
。obj.method(instance.arrowFunction)
:由于箭头函数继承了创建时的this
值(即instance
),无论如何调用它,this
都将保持指向instance
。所以,输出的值是"Arrow function: Class value"
。
问题3:现在假设我们有一个异步操作如下:
setTimeout(instance.regularFunction, 1000);
请解释这段代码中的this指向,以及为什么是这样的指向。
在这个例子中,当instance.regularFunction
作为回调函数传递给setTimeout
时,它会在全局上下文(浏览器中为window
,Node.js中为global
)中执行。因此,this
将指向全局对象。如果strict mode
没有启用,输出的值是"Regular function: undefined"
。在strict mode
下,this
为undefined
,将导致抛出错误。
如果需要保持this
指向实例,可以通过以下几种方法之一来修改代码:
- 使用
bind
方法将this
绑定到实例:
setTimeout(instance.regularFunction.bind(instance), 1000);
- 使用箭头函数作为回调函数,并在其中调用
instance.regularFunction()
:
setTimeout(() => instance.regularFunction(), 1000);
这样修改后,setTimeout
中的this
将始终指向instance
,并输出"Regular function: Class value"
。
原文链接:https://juejin.cn/post/7232234470779093049 作者:2002XiaoYu