JavaScript中的“this”是什么?

163 阅读3分钟

JavaScript中的“this”是什么?

在JavaScript中,this​关键字指的是正在执行代码的当前对象。this​的值可能会根据函数的调用方式而改变。

以下是一个示例,说明this的值如何在不同的上下文中发生变化:

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

obj.sayHello(); // Output: "Hello, my name is John"

const greeting = obj.sayHello;
greeting(); // Output: "Hello, my name is undefined"

在第一次调用sayHello​时,this​指的是obj​,因为该函数是作为obj​上的方法调用的。

在对sayHello​的第二次调用中,该函数被分配给变量​greeting​,并作为常规函数调用。所以,在这种情况下,this​指的是全局对象(在浏览器中,这是​window​对象)。由于没有在全局级别声明变量​name​,它解析为​undefined​。

什么是绑定?

在JavaScript中,绑定是指设置this​关键字值的过程。当调用一个函数时,该函数中this​的值由函数的调用方式决定。

不要将绑定与bind()方法混淆!

有哪些不同类型的绑定?

有4种类型的绑定:

  • 隐式绑定
  • 显式绑定
  • 全局绑定
  • 无绑定(箭头函数)

隐式绑定

在JavaScript中,隐式绑定​是指调用函数时确定this​关键字值的方式。如果函数作为对象上的方法调用,则this​的值设置为函数内的对象。这被称为“隐式绑定”,因为this的值是根据调用函数的上下文隐式(自动)确定的。

这是一个隐式绑定的示例:

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

obj.sayHello(); // Output: "Hello, my name is John"

在上面的例子中,sayHello​函数作为obj​上的方法被调用,所以函数中this​的值被设置为obj​。当函数执行时,它输出“Hello, my name is John”,因为this.name​相当于obj.name​,也就是“John”。

显式绑定

在JavaScript中,显式绑定是指使用​bind​、​call​或​apply​方法显式(手动)设置this​关键字的值的过程。

bind​方法创建一个新函数,其主体和参数与原始函数相同,但this​的值永久设置为传递给bind​的第一个参数。

以下是使用bind​方法创建具有显式值​this​的新函数的示例:

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

const greeting = obj.sayHello.bind(obj);
greeting(); // Output: "Hello, my name is John"

call​和​apply​方法的工作方式类似于bind​,但它们会立即使用this​的指定值调用函数,而不是返回新函数。

以下是使用call​方法调用具有显式值this​的函数的示例:

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

obj.sayHello.call(obj); // Output: "Hello, my name is John"

apply​方法与​call​相同,但有一点不同。虽然call​方法接受参数作为逗号分隔值,但​apply​逗号分隔值方法接受它们作为数组。

全局绑定

在JavaScript中,this​关键字的值由调用函数的上下文决定,在全局执行上下文中(即在任何函数之外),this​的值被设置为全局对象。

在浏览器中全局对象是window​对象,所以this​在全局执行上下文中的值是window​对象

下面是如何在全局执行上下文中将this的值设置为全局对象的示例:

console.log(this); // Output: Window {...}

function sayHello() {
  console.log(`Hello, my name is ${this.name}`);
}

sayHello(); // Output: "Hello, my name is undefined"

在上面的例子中,this​被设置为全局执行上下文中的全局对象(​window​对象),当调用sayHello​函数时,函数内this​的值也被设置为全局对象,因为函数被作为独立函数调用(而不是作为对象上的方法)

请注意,在严格模式下(当在脚本或函数的顶部使用“使用严格”指令时),全局执行上下文中this的值是未定义的,而不是全局对象。

无绑定:箭头函数和this关键字

在JavaScript中,箭头函数(也称为“胖箭头函数”)是编写函数表达式的一种简洁方式。与常规函数不同,箭头函数没有自己的this​值。相反,它们继承周围上下文的this​值。

以下是使用this关键字的箭头函数示例:

const obj = {
  name: 'John',
  sayHello: () => {
    console.log(`Hello, my name is ${this.name}`);
  }
};

obj.sayHello(); // Output: "Hello, my name is undefined"

在上面的例子中,sayHello​函数是一个箭头函数,它使用this​关键字来访问obj​对象的name​属性。但是,当调用该函数时,它会输出“Hello, my name is undefined”,因为函数中this​的值没有按预期设置为obj​。

这是因为箭头函数没有自己的this​值;它们继承周围上下文的this​值。在这种情况下,箭头函数中的this​值是全局对象(在浏览器中是​window​对象),因为箭头函数不是作为对象上的方法调用的。

如果您想在箭头函数中使用this​关键字并让它引用定义函数的对象,您可以在常规函数中使用箭头函数,或者使用bind​方法显式设置this​的值。

以下是在常规函数中使用箭头函数来访问周围上下文的this​值的示例:

const obj = {
  name: 'John',
  sayHello: function() {
    const sayName = () => {
      console.log(`Hello, my name is ${this.name}`);
    };
    sayName(); // Output: "Hello, my name is John"
  }
};

obj.sayHello();

在上面的例子中,sayName​箭头函数是在sayHello​函数内部定义的,因此它可以访问sayHello​函数的this​值,即obj​。当调用sayName​函数时,它会输出“Hello, my name is John”,因为this.name​的值obj.name​,即“John​”。

进一步阅读