问题描述
我在JavaScript中有一个关于this
的问题。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
我读这篇文章时说
在箭头函数中,
this
保留封闭的词法上下文this的值。在全局代码中,它将被设置为全局对象
但是例如下面的代码
const person = {
hobby: "loafing around",sayHobby: function() {
setTimeout(() => {
console.log(`My hobby is ${this.hobby}`);
},100);
}
};
person.sayHobby()
在此示例中,setTimeout函数包含了setTimeout中的Arrow函数回调。所以我认为this
应该是global(window),因为setTimeout是在全球对象中定义的。
我知道我的想法是错误的,但是不知道如何理解enclosing lexical context
的含义。你能帮我了解一下吗?如何找到词汇上下文?
解决方法
在全局范围内,this
指向全局对象(在浏览器中将是窗口)。
现在,当您调用person.sayHobby()
时,sayHobby
不是箭头功能。因此,此调用将创建一个新的词法上下文,其中this
指向.
中person.sayHobby()
的左侧,即人对象。
接下来,您呼叫setTimeout
,它等效于window.setTimeout
。 setTimeout
的调用将具有词法范围,其中this
的结果为window。但是我们看不到这一点,因为setTimeout
是内部浏览器方法。您看不到它的代码。
调用setTimeout
时,您将传递一个函数参数。该论点包括调用者的词汇上下文。因此,setTimeout
然后调用您的arrow函数,并使用传递的词法上下文对其进行调用。
// global context
// this evaluates to window. This should output true
console.log('this here evaluates to window: ' + (window === this));
const person = {
hobby: "loafing around",sayHobby: function() {
// This is a non arrow function. It creates a new lexical context
// This should also print true
console.log('this evaluates to the person object used for the call: ' + (this.hobby === 'loafing around'));
// setTimeout is called without this
// Any call without this. preceding it assumes that the function is in global object.
// So this is the same as window.setTimeout
setTimeout(() => {
// This is an arrow function. No new scope is created.
// This should print true
console.log('this evaluates to the person object used for the sayHobby call: ' + (this.hobby === 'loafing around'));
console.log(`My hobby is ${this.hobby}`);
},100);
}
};
// Calling person.sayHobby will make this evaluate to person inside the sayHobby() call
person.sayHobby();
现在让我们更改代码,并在globalScope中定义一个全局函数
//
function myGlobalFunction(callback) {
console.log('inside myGlobalFunction this evaluates to window: ' + (window === this));
callback();
}
// global context
// this evaluates to window. This should output true
console.log('this here evaluates to window: ' + (window === this));
const person = {
hobby: "loafing around",sayHobby: function() {
// This is a non arrow function. It creates a new lexical context
// This should also print true
console.log('this evaluates to the person object used for the call: ' + (this.hobby === 'loafing around'));
// setTimeout is called without this
// Any call without this. preceding it assumes that the function is in global object.
// So this is the same as window.setTimeout
myGlobalFunction(() => {
// This is an arrow function. No new scope is created.
// This should print true
console.log('this evaluates to the person object used for the sayHobby call: ' + (this.hobby === 'loafing around'));
console.log(`My hobby is ${this.hobby}`);
},100);
}
};
// Calling person.sayHobby will make this evaluate to person inside the sayHobby() call
person.sayHobby();
这基本上是相同的。在myGlobalFunction
内,全局上下文中有this
指向window
。但是callback
参数包括调用方的上下文。因此,callback()
将以人员为上下文执行。