Javascript 使用arrow函数时封闭词汇上下文的意义(词汇this)
我对javascript中的Javascript 使用arrow函数时封闭词汇上下文的意义(词汇this),javascript,this,Javascript,This,我对javascript中的这个有一个问题 当我读到这篇文章时,它说 在箭头函数中,this保留封闭词法上下文的this值。在全局代码中,它将被设置为全局对象 但例如,下面的代码 const person={ 爱好:“游手好闲”, sayHobby:function(){ 设置超时(()=>{ log(`My hobby is${this.hobby}`); }, 100); } }; person.sayHobby()在全局范围中,此指向全局对象(在浏览器中它将显示在窗口中)。 现在,当您
这个有一个问题
当我读到这篇文章时,它说
在箭头函数中,this
保留封闭词法上下文的this值。在全局代码中,它将被设置为全局对象
但例如,下面的代码
const person={
爱好:“游手好闲”,
sayHobby:function(){
设置超时(()=>{
log(`My hobby is${this.hobby}`);
}, 100);
}
};
person.sayHobby()
在全局范围中,此
指向全局对象(在浏览器中它将显示在窗口中)。
现在,当您调用person.sayHobby()
时,sayHobby
不是一个箭头函数。因此,此调用创建一个新的词汇上下文,其中this
指向person.sayHobby()
中
左侧的任何对象,即person对象
接下来调用setTimeout
,它相当于window.setTimeout
。setTimeout
调用将具有词法作用域,其中此
的计算结果为窗口。但是我们没有看到这一点,因为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
内部,全局上下文是hasthis
指向窗口
。但是callback
参数包含调用者的上下文。因此,执行callback()
时将person作为上下文。它将作用域扩展到容器对象,因此在本例中扩展到person
对象。“箭头函数由setTimeout函数包围”-不,这只是一个不改变作用域的函数调用。周围的范围是函数(){…}
定义的范围。如果你调用person.sayHobby
,那么sayHobby
方法中的this
值(以及其中定义的箭头函数)将变成person
。啊,现在我意识到了我的错误。我把函数调用和函数声明搞混了。所以,实际上箭头函数是在函数作用域sayHobby
中定义的setTimeout
就像@Bergi说的那样是一个调用。@MisterJojo很好,但那是错误的。充其量,箭头函数“属于”于sayHobby
。但实际上它只是使用了相同的这个值,这取决于sayHobby
的调用方式。@wpark是的,没错。如果你做了person.sayHobby.call({hobby:'something'})
,它会使用不同的这个值。超级清晰的答案,让我开悟。谢谢你!