Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用arrow函数时封闭词汇上下文的意义(词汇this)_Javascript_This - Fatal编程技术网

Javascript 使用arrow函数时封闭词汇上下文的意义(词汇this)

Javascript 使用arrow函数时封闭词汇上下文的意义(词汇this),javascript,this,Javascript,This,我对javascript中的这个有一个问题 当我读到这篇文章时,它说 在箭头函数中,this保留封闭词法上下文的this值。在全局代码中,它将被设置为全局对象 但例如,下面的代码 const person={ 爱好:“游手好闲”, sayHobby:function(){ 设置超时(()=>{ log(`My hobby is${this.hobby}`); }, 100); } }; person.sayHobby()在全局范围中,此指向全局对象(在浏览器中它将显示在窗口中)。 现在,当您

我对javascript中的
这个
有一个问题

当我读到这篇文章时,它说

在箭头函数中,
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
内部,全局上下文是has
this
指向
窗口
。但是
callback
参数包含调用者的上下文。因此,执行
callback()
时将person作为上下文。

它将作用域扩展到容器对象,因此在本例中扩展到
person
对象。“箭头函数由setTimeout函数包围”-不,这只是一个不改变作用域的函数调用。周围的范围是
函数(){…}
定义的范围。如果你调用
person.sayHobby
,那么
sayHobby
方法中的
this
值(以及其中定义的箭头函数)将变成
person
。啊,现在我意识到了我的错误。我把函数调用和函数声明搞混了。所以,实际上箭头函数是在函数作用域
sayHobby
中定义的
setTimeout
就像@Bergi说的那样是一个调用。@MisterJojo很好,但那是错误的。充其量,箭头函数“属于”于
sayHobby
。但实际上它只是使用了相同的
这个
值,这取决于
sayHobby
的调用方式。@wpark是的,没错。如果你做了
person.sayHobby.call({hobby:'something'})
,它会使用不同的
这个值。超级清晰的答案,让我开悟。谢谢你!