使用箭头功能时包含词法上下文的含义词法此

问题描述

我在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.setTimeoutsetTimeout的调用将具有词法范围,其中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()将以人员为上下文执行。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...