GGbond : 聊聊JavaScript的this指向

213 阅读3分钟

JavaScript中的this是一个非常重要但也容易混淆的概念。this指的是当前执行上下文中的对象,它可以根据不同的情况而变化。

1. 全局上下文中的this

在全局上下文中,即不在任何函数或对象内部的代码中,this指向全局对象。

在浏览器环境中,全局对象就是window对象。例如:

console.log(this); // window
console.log(this === window); // true
var name = "Bing";
console.log(this.name); // Bing

2. 函数中的this

在函数中,this的指向取决于函数是如何被调用的。一般来说,有以下几种情况:

  • 普通函数调用:如果一个函数是直接被调用的,那么this指向全局对象。例如:
function sayHello() {
  console.log(this); // window
  console.log(this.name); // Bing
}
sayHello();
  • 对象方法调用:如果一个函数是作为对象的方法被调用的,那么this指向该对象。例如:
var person = {
  name: "Alice",
  sayHello: function() {
    console.log(this); // person
    console.log(this.name); // Alice
  }
};
person.sayHello();
  • 构造函数调用:如果一个函数是作为构造函数被调用的,即使用new关键字创建一个新对象,那么this指向该新对象。例如:
function Person(name) {
  this.name = name;
  this.sayHello = function() {
    console.log(this); // 新创建的对象
    console.log(this.name); // 新创建对象的name属性
  };
}
var bob = new Person("Bob");
bob.sayHello();
  • 显示绑定:如果一个函数使用了call、apply或bind方法来显示地绑定this的值,那么this指向绑定的对象。例如:
function sayHello() {
  console.log(this); // 绑定的对象
  console.log(this.name); // 绑定对象的name属性
}
var car = {
  name: "Tesla"
};
sayHello.call(car); // 使用call方法绑定car对象为this
sayHello.apply(car); // 使用apply方法绑定car对象为this
var sayHelloToCar = sayHello.bind(car); // 使用bind方法返回一个新函数,该函数的this绑定为car对象
sayHelloToCar();
  • 箭头函数:如果一个函数是箭头函数,那么它没有自己的this,而是继承了外层作用域中的this。例如:
var name = "Bing";
var sayHello = () => {
  console.log(this); // window
  console.log(this.name); // Bing
};
sayHello();
var person = {
  name: "Alice",
  sayHello: () => {
    console.log(this); // window
    console.log(this.name); // Bing
  }
};
person.sayHello();

3. 类中的this

在类中,this指向类的实例对象。在类的构造函数和方法中,可以使用this来访问或修改实例对象的属性和方法。例如:

class Person {
  constructor(name) {
    this.name = name; // 使用this给实例对象添加name属性
  }
  sayHello() {
    console.log(this); // 实例对象
    console.log(`Hello, I am ${this.name}`); // 使用this访问实例对象的name属性
  }
}
var alice = new Person("Alice");
alice.sayHello();

4. 模块中的this

在模块中,this指向undefined,而不是全局对象。模块是一种特殊的脚本,可以使用import和export关键字来导入和导出变量或函数。 模块默认开启严格模式,所以this不能指向全局对象。 例如:

// module.js
console.log(this); // undefined
export const name = "Bing";

5. with语句中的this

在with语句中,this指向with语句的参数对象。with语句是一种不推荐使用的语法,可以扩展一个对象的作用域链。在with语句的代码块中,可以直接访问对象的属性和方法,而不需要使用点或方括号。例如:

var car = {
  name: "Tesla",
  price: 50000,
};
with (car) {
  console.log(this); // car对象
  console.log(name); // Tesla
  console.log(price); // 50000
}

总结:

JavaScript中的this是一个动态的概念,它指向当前执行上下文中的对象。this的指向取决于函数是如何被调用的,有以下几种常见的情况:

  • 全局上下文中的this指向全局对象,如window
  • 对象方法调用中的this指向该对象
  • 构造函数调用中的this指向新创建的对象
  • 显示绑定中的this指向绑定的对象,如使用call、apply或bind方法
  • 箭头函数中的this继承了外层作用域中的this

此外,还有一些特殊的情况,需要注意this的用法:

  • 类中的this指向类的实例对象
  • 模块中的this指向undefined,而不是全局对象
  • with语句中的this指向with语句的参数对象