返回

从执行上下文(作用域)理解this

前端

理解this的含义在JavaScript中至关重要,它可以帮助你写出更健壮、更可维护的代码。this关键字的作用域会随着代码的执行上下文而改变,而执行上下文决定了this的指向。

执行上下文(作用域)
执行上下文是在特定时间运行的代码的集合。在 JavaScript 中,有两种类型的执行上下文:全局执行上下文和函数执行上下文。

全局执行上下文
当 JavaScript 代码开始执行时,就会创建一个全局执行上下文。全局执行上下文的作用域包括所有在全局代码块中声明的变量和函数。this关键字在全局执行上下文中指向window对象。

函数执行上下文
当一个函数被调用时,就会创建一个函数执行上下文。函数执行上下文的作用域包括函数内部声明的所有变量和参数。this关键字在函数执行上下文中指向调用该函数的对象。

例如:

function Person(name) {
  this.name = name;
}

const person = new Person('John');

console.log(person.name); // John

在这个示例中,当Person函数被调用时,就会创建一个函数执行上下文。this关键字在Person函数的执行上下文中指向person对象。因此,person.name属性的值为'John'。

this的指向
this关键字的指向取决于它所在执行上下文的类型。在全局执行上下文中,this指向window对象。在函数执行上下文中,this指向调用该函数的对象。

改变this的指向
可以通过以下方式改变this的指向:

  • 使用call()、apply()或bind()方法
  • 使用箭头函数

例如:

const person = {
  name: 'John',
  greet: function() {
    console.log(`Hello, my name is ${this.name}`);
  }
};

person.greet(); // Hello, my name is John

const button = document.getElementById('button');
button.addEventListener('click', person.greet); // Hello, my name is undefined

button.addEventListener('click', person.greet.bind(person)); // Hello, my name is John

在这个示例中,当按钮被点击时,person.greet()方法就会被调用。但是,this关键字在button的执行上下文中指向button对象,而不是person对象。因此,console.log()语句会输出"Hello, my name is undefined"。

为了解决这个问题,可以使用bind()方法来改变this的指向。bind()方法返回一个新的函数,该函数的this关键字指向指定的对象。在这个示例中,bind()方法被用来将this关键字指向person对象。因此,console.log()语句会输出"Hello, my name is John"。