this

this 关键字指的是一段代码(例如函数体)应该运行的上下文。最典型的是,它用在对象方法中,其中 this 指的是该方法所附加的对象,从而允许在不同的对象上重用相同的方法。

¥The this keyword refers to the context where a piece of code, such as a function's body, is supposed to run. Most typically, it is used in object methods, where this refers to the object that the method is attached to, thus allowing the same method to be reused on different objects.

JavaScript 中 this 的值取决于函数的调用方式(运行时 binding),而不是其定义方式。当常规函数作为对象 (obj.method()) 的方法调用时,this 指向该对象。当作为独立函数调用时(未附加到对象:func()),this 通常指的是 全局对象(在非严格模式中)或 undefined(在 严格模式 中)。Function.prototype.bind() 方法可以创建一个 this 绑定不变的函数,方法 apply()call() 还可以为特定调用设置 this 值。

¥The value of this in JavaScript depends on how a function is invoked (runtime binding), not how it is defined. When a regular function is invoked as a method of an object (obj.method()), this points to that object. When invoked as a standalone function (not attached to an object: func()), this typically refers to the global object (in non-strict mode) or undefined (in strict mode). The Function.prototype.bind() method can create a function whose this binding doesn't change, and methods apply() and call() can also set the this value for a particular call.

箭头函数this 的处理有所不同:它们在定义时从父作用域继承 this。这种行为使得箭头函数对于回调和保留上下文特别有用。但是,箭头函数没有自己的 this 绑定。因此,它们的 this 值不能通过 bind()apply()call() 方法设置,也不能在对象方法中指向当前对象。

¥Arrow functions differ in their handling of this: they inherit this from the parent scope at the time they are defined. This behavior makes arrow functions particularly useful for callbacks and preserving context. However, arrow functions do not have their own this binding. Therefore, their this value cannot be set by bind(), apply() or call() methods, nor does it point to the current object in object methods.

Try it

语法

¥Syntax

js
this

¥Value

在非严格模式下,this 始终是对对象的引用。在严格模式下,它可以是任何值。有关如何确定该值的更多信息,请参阅下面的描述。

¥In non–strict mode, this is always a reference to an object. In strict mode, it can be any value. For more information on how the value is determined, see the description below.

描述

¥Description

this 的值取决于它出现的上下文:函数、类或全局。

¥The value of this depends on in which context it appears: function, class, or global.

函数上下文

¥Function context

在函数内部,this 的值取决于函数的调用方式。将 this 视为函数的隐藏参数 - 就像函数定义中声明的参数一样,this 是在评估函数体时语言为你创建的绑定。

¥Inside a function, the value of this depends on how the function is called. Think about this as a hidden parameter of a function — just like the parameters declared in the function definition, this is a binding that the language creates for you when the function body is evaluated.

对于常规函数(不是箭头函数、绑定函数等),this 的值是访问该函数的对象。换句话说,如果函数调用的形式为 obj.f(),则 this 指的是 obj。例如:

¥For a regular function (not an arrow function, bound function, etc.), the value of this is the object that the function is accessed on. In other words, if the function call is in the form obj.f(), then this refers to obj. For example:

js
function getThis() {
  return this;
}

const obj1 = { name: "obj1" };
const obj2 = { name: "obj2" };

obj1.getThis = getThis;
obj2.getThis = getThis;

console.log(obj1.getThis()); // { name: 'obj1', getThis: [Function: getThis] }
console.log(obj2.getThis()); // { name: 'obj2', getThis: [Function: getThis] }

请注意,该函数是相同的,但根据其调用方式,this 的值有所不同。这类似于函数参数的工作方式。

¥Note how the function is the same, but based on how it's invoked, the value of this is different. This is analogous to how function parameters work.

this 的值不是将该函数作为自己的属性的对象,而是用于调用该函数的对象。你可以通过调用 原型链 中对象的方法来证明这一点。

¥The value of this is not the object that has the function as an own property, but the object that is used to call the function. You can prove this by calling a method of an object up in the prototype chain.

js
const obj3 = {
  __proto__: obj1,
  name: "obj3",
};

console.log(obj3.getThis()); // { name: 'obj3' }

this 的值总是根据函数的调用方式而变化,即使该函数是在创建时在对象上定义的:

¥The value of this always changes based on how a function is called, even when the function was defined on an object at creation:

js
const obj4 = {
  name: "obj4",
  getThis() {
    return this;
  },
};

const obj5 = { name: "obj5" };

obj5.getThis = obj4.getThis;
console.log(obj5.getThis()); // { name: 'obj5', getThis: [Function: getThis] }

如果访问该方法的值是原始值,则 this 也将是原始值 - 但前提是该函数处于严格模式。

¥If the value that the method is accessed on is a primitive, this will be a primitive value as well — but only if the function is in strict mode.

js
function getThisStrict() {
  "use strict"; // Enter strict mode
  return this;
}

// Only for demonstration — you should not mutate built-in prototypes
Number.prototype.getThisStrict = getThisStrict;
console.log(typeof (1).getThisStrict()); // "number"

如果在没有任何内容访问的情况下调用该函数,则 this 将是 undefined — 但前提是该函数处于严格模式。

¥If the function is called without being accessed on anything, this will be undefined — but only if the function is in strict mode.

js
console.log(typeof getThisStrict()); // "undefined"

在非严格模式下,一个名为 this 替换 的特殊进程确保 this 的值始终是一个对象。这意味着:

¥In non-strict mode, a special process called this substitution ensures that the value of this is always an object. This means:

  • 如果调用函数时将 this 设置为 undefinednull,则 this 将替换为 globalThis
  • 如果调用该函数时将 this 设置为原始值,则 this 将替换为原始值的封装对象。
js
function getThis() {
  return this;
}

// Only for demonstration — you should not mutate built-in prototypes
Number.prototype.getThis = getThis;
console.log(typeof (1).getThis()); // "object"
console.log(getThis() === globalThis); // true

在典型的函数调用中,this 像参数一样通过函数的前缀(点之前的部分)隐式传递。你还可以使用 Function.prototype.call()Function.prototype.apply()Reflect.apply() 方法显式设置 this 的值。使用 Function.prototype.bind(),你可以创建一个具有特定值 this 的新函数,无论如何调用该函数,该值都不会改变。使用这些方法时,如果函数是非严格的,则上述 this 替换规则仍然适用。

¥In typical function calls, this is implicitly passed like a parameter through the function's prefix (the part before the dot). You can also explicitly set the value of this using the Function.prototype.call(), Function.prototype.apply(), or Reflect.apply() methods. Using Function.prototype.bind(), you can create a new function with a specific value of this that doesn't change regardless of how the function is called. When using these methods, the this substitution rules above still apply if the function is non-strict.

回调

¥Callbacks

当函数作为回调传递时,this 的值取决于回调的调用方式,这由 API 的实现者确定。回调通常使用 thisundefined 进行调用(直接调用它而不将其附加到任何对象),这意味着如果函数是非严格的,则 this 的值是全局对象 (globalThis)。迭代数组方法Promise() 构造函数等就是这种情况。

¥When a function is passed as a callback, the value of this depends on how the callback is called, which is determined by the implementor of the API. Callbacks are typically called with a this value of undefined (calling it directly without attaching it to any object), which means if the function is non–strict, the value of this is the global object (globalThis). This is the case for iterative array methods, the Promise() constructor, etc.

js
function logThis() {
  "use strict";
  console.log(this);
}

[1, 2, 3].forEach(logThis); // undefined, undefined, undefined

某些 API 允许你为回调调用设置 this 值。例如,所有迭代数组方法和相关方法(例如 Set.prototype.forEach())都接受可选的 thisArg 参数。

¥Some APIs allow you to set a this value for invocations of the callback. For example, all iterative array methods and related ones like Set.prototype.forEach() accept an optional thisArg parameter.

js
[1, 2, 3].forEach(logThis, { name: "obj" });
// { name: 'obj' }, { name: 'obj' }, { name: 'obj' }

有时,会使用 this 值而不是 undefined 来调用回调。例如,JSON.parse()reviver 参数和 JSON.stringify()replacer 参数都被调用,并且 this 设置为正在解析/序列化的属性所属的对象。

¥Occasionally, a callback is called with a this value other than undefined. For example, the reviver parameter of JSON.parse() and the replacer parameter of JSON.stringify() are both called with this set to the object that the property being parsed/serialized belongs to.

箭头函数

¥Arrow functions

箭头函数 中,this 保留封闭词法上下文的 this 的值。换句话说,当评估箭头函数的主体时,该语言不会创建新的 this 绑定。

¥In arrow functions, this retains the value of the enclosing lexical context's this. In other words, when evaluating an arrow function's body, the language does not create a new this binding.

例如,在全局代码中,无论严格性如何,this 始终是 globalThis,因为 全球背景 绑定:

¥For example, in global code, this is always globalThis regardless of strictness, because of the global context binding:

js
const globalObject = this;
const foo = () => this;
console.log(foo() === globalObject); // true

箭头函数在其周围范围的 this 值上创建 closure,这意味着箭头函数的行为就好像它们是 "auto-bound" — 无论如何调用它,this 都绑定到创建该函数时的值(在上面的示例中, 全局对象)。这同样适用于在其他函数内创建的箭头函数:它们的 this 仍然是封闭的词汇上下文的 this请参阅下面的示例

¥Arrow functions create a closure over the this value of its surrounding scope, which means arrow functions behave as if they are "auto-bound" — no matter how it's invoked, this is bound to what it was when the function was created (in the example above, the global object). The same applies to arrow functions created inside other functions: their this remains that of the enclosing lexical context. See example below.

此外,当使用 call()bind()apply() 调用箭头函数时,thisArg 参数将被忽略。不过,你仍然可以使用这些方法传递其他参数。

¥Furthermore, when invoking arrow functions using call(), bind(), or apply(), the thisArg parameter is ignored. You can still pass other arguments using these methods, though.

js
const obj = { name: "obj" };

// Attempt to set this using call
console.log(foo.call(obj) === globalObject); // true

// Attempt to set this using bind
const boundFoo = foo.bind(obj);
console.log(boundFoo() === globalObject); // true

构造函数

¥Constructors

当函数用作构造函数时(使用 new 关键字),其 this 绑定到正在构造的新对象,无论构造函数在哪个对象上访问。除非构造函数返回另一个非原始值,否则 this 的值将成为 new 表达式的值。

¥When a function is used as a constructor (with the new keyword), its this is bound to the new object being constructed, no matter which object the constructor function is accessed on. The value of this becomes the value of the new expression unless the constructor returns another non–primitive value.

js
function C() {
  this.a = 37;
}

let o = new C();
console.log(o.a); // 37

function C2() {
  this.a = 37;
  return { a: 38 };
}

o = new C2();
console.log(o.a); // 38

在第二个示例(C2)中,由于在构造过程中返回了一个对象,因此 this 绑定到的新对象被丢弃。(这实质上使语句 this.a = 37; 成为死代码。它并不完全是死代码,因为它被执行了,但它可以在没有外部影响的情况下被消除。)

¥In the second example (C2), because an object was returned during construction, the new object that this was bound to gets discarded. (This essentially makes the statement this.a = 37; dead code. It's not exactly dead because it gets executed, but it can be eliminated with no outside effects.)

super

当以 super.method() 形式调用函数时,method 函数内部的 thissuper.method() 调用周围的 this 值相同,并且通常不等于 super 引用的对象。这是因为 super.method 不是像上面那样的对象成员访问 - 它是具有不同绑定规则的特殊语法。例如,请参见 super 参考

¥When a function is invoked in the super.method() form, the this inside the method function is the same value as the this value around the super.method() call, and is generally not equal to the object that super refers to. This is because super.method is not an object member access like the ones above — it's a special syntax with different binding rules. For examples, see the super reference.

类背景

¥Class context

class 可以分为两个上下文:静态和实例。构造函数、方法和实例字段初始值设定项(publicprivate)属于实例上下文。静止的 方法、静态字段初始值设定项和 静态初始化块 属于静态上下文。this 值在每个上下文中都不同。

¥A class can be split into two contexts: static and instance. Constructors, methods, and instance field initializers (public or private) belong to the instance context. Static methods, static field initializers, and static initialization blocks belong to the static context. The this value is different in each context.

类构造函数始终使用 new 调用,因此它们的行为与 函数构造函数 相同:this 值是正在创建的新实例。类方法的行为类似于对象字面量中的方法 - this 值是访问该方法的对象。如果方法没有转移到另一个对象,this 一般是该类的一个实例。

¥Class constructors are always called with new, so their behavior is the same as function constructors: the this value is the new instance being created. Class methods behave like methods in object literals — the this value is the object that the method was accessed on. If the method is not transferred to another object, this is generally an instance of the class.

静态方法不是 this 的属性。它们是类本身的属性。因此,一般是在类上访问它们,this 是该类(或子类)的值。静态初始化块也会通过设置为当前类的 this 进行评估。

¥Static methods are not properties of this. They are properties of the class itself. Therefore, they are generally accessed on the class, and this is the value of the class (or a subclass). Static initialization blocks are also evaluated with this set to the current class.

字段初始值设定项也在类的上下文中进行评估。实例字段通过设置为正在构造的实例的 this 进行评估。静态字段通过设置为当前类的 this 进行评估。这就是为什么字段初始值设定项中的箭头函数是 对于实例字段绑定到实例,对于静态字段绑定到类

¥Field initializers are also evaluated in the context of the class. Instance fields are evaluated with this set to the instance being constructed. Static fields are evaluated with this set to the current class. This is why arrow functions in field initializers are bound to the instance for instance fields and to the class for static fields.

js
class C {
  instanceField = this;
  static staticField = this;
}

const c = new C();
console.log(c.instanceField === c); // true
console.log(C.staticField === C); // true

派生类构造函数

¥Derived class constructors

与基类构造函数不同,派生构造函数没有初始 this 绑定。调用 super() 会在构造函数中创建 this 绑定,并且本质上具有评估以下代码行的效果,其中 Base 是基类:

¥Unlike base class constructors, derived constructors have no initial this binding. Calling super() creates a this binding within the constructor and essentially has the effect of evaluating the following line of code, where Base is the base class:

js
this = new Base();

警告:在调用 super() 之前引用 this 会引发错误。

¥Warning: Referring to this before calling super() will throw an error.

派生类在调用 super() 之前不得返回,除非构造函数返回一个对象(因此 this 值被覆盖)或者该类根本没有构造函数。

¥Derived classes must not return before calling super(), unless the constructor returns an object (so the this value is overridden) or the class has no constructor at all.

js
class Base {}
class Good extends Base {}
class AlsoGood extends Base {
  constructor() {
    return { a: 5 };
  }
}
class Bad extends Base {
  constructor() {}
}

new Good();
new AlsoGood();
new Bad(); // ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor

全球背景

¥Global context

在全局执行上下文中(在任何函数或类之外;可能在全局作用域中定义的 blocks箭头函数 内部),this 值取决于脚本运行的执行上下文。与 callbacks 一样,this 值由运行时环境(调用者)决定。

¥In the global execution context (outside of any functions or classes; may be inside blocks or arrow functions defined in the global scope), the this value depends on what execution context the script runs in. Like callbacks, the this value is determined by the runtime environment (the caller).

在脚本的顶层,this 引用 globalThis,无论是否处于严格模式。这通常与全局对象相同 - 例如,如果源放入 HTML <script> 元素内并作为脚本执行,则 this === window

¥At the top level of a script, this refers to globalThis whether in strict mode or not. This is generally the same as the global object — for example, if the source is put inside an HTML <script> element and executed as a script, this === window.

注意:globalThis 通常与全局对象是相同的概念(即向 globalThis 添加属性使它们成为全局变量) - 浏览器和 Node 就是这种情况 - 但允许主机为 globalThis 提供与全局对象无关的不同值。

¥Note: globalThis is generally the same concept as the global object (i.e. adding properties to globalThis makes them global variables) — this is the case for browsers and Node — but hosts are allowed to provide a different value for globalThis that's unrelated to the global object.

js
// In web browsers, the window object is also the global object:
console.log(this === window); // true

this.b = "MDN";
console.log(window.b); // "MDN"
console.log(b); // "MDN"

如果源作为 module 加载(对于 HTML,这意味着将 type="module" 添加到 <script> 标记),则 this 始终是顶层的 undefined

¥If the source is loaded as a module (for HTML, this means adding type="module" to the <script> tag), this is always undefined at the top level.

如果使用 eval() 执行源,则 this直接评估globalThis 的封闭上下文相同(就好像它在单独的全局脚本中运行)以进行间接评估。

¥If the source is executed with eval(), this is the same as the enclosing context for direct eval, or globalThis (as if it's run in a separate global script) for indirect eval.

js
function test() {
  // Direct eval
  console.log(eval("this") === this);
  // Indirect eval, non-strict
  console.log(eval?.("this") === globalThis);
  // Indirect eval, strict
  console.log(eval?.("'use strict'; this") === globalThis);
}

test.call({ name: "obj" }); // Logs 3 "true"

请注意,某些源代码虽然看起来像全局范围,但在执行时实际上封装在函数中。例如,Node.js CommonJS 模块封装在一个函数中,并使用设置为 module.exportsthis 值执行。事件处理程序属性 执行时将 this 设置为它们所附加的元素。

¥Note that some source code, while looking like the global scope, is actually wrapped in a function when executed. For example, Node.js CommonJS modules are wrapped in a function and executed with the this value set to module.exports. Event handler attributes are executed with this set to the element they are attached to.

对象字面量不会创建 this 作用域 — 只有在对象内定义的函数(方法)才会创建。在对象字面量中使用 this 会继承周围范围的值。

¥Object literals don't create a this scope — only functions (methods) defined within the object do. Using this in an object literal inherits the value from the surrounding scope.

js
const obj = {
  a: this,
};

console.log(obj.a === window); // true

示例

¥Examples

this 在函数上下文中

¥this in function contexts

this 参数的值取决于函数的调用方式,而不是其定义方式。

¥The value of the this parameter depends on how the function is called, not on how it's defined.

js
// An object can be passed as the first argument to 'call'
// or 'apply' and 'this' will be bound to it.
const obj = { a: "Custom" };

// Variables declared with var become properties of 'globalThis'.
var a = "Global";

function whatsThis() {
  return this.a; // 'this' depends on how the function is called
}

whatsThis(); // 'Global'; the 'this' parameter defaults to 'globalThis' in non–strict mode
obj.whatsThis = whatsThis;
obj.whatsThis(); // 'Custom'; the 'this' parameter is bound to obj

使用 call()apply(),你可以传递 this 的值,就像它是显式参数一样。

¥Using call() and apply(), you can pass the value of this as if it's an explicit parameter.

js
function add(c, d) {
  return this.a + this.b + c + d;
}

const o = { a: 1, b: 3 };

// The first argument is bound to the implicit 'this' parameter; the remaining
// arguments are bound to the named parameters.
add.call(o, 5, 7); // 16

// The first argument is bound to the implicit 'this' parameter; the second
// argument is an array whose members are bound to the named parameters.
add.apply(o, [10, 20]); // 34

this 和对象转换

¥this and object conversion

在非严格模式下,如果使用不是对象的 this 值调用函数,则 this 值将替换为对象。nullundefined 变成 globalThis。像 7'foo' 这样的基元会使用相关的构造函数转换为对象,因此基元数字 7 会转换为 Number 封装类,字符串 'foo' 会转换为 String 封装类。

¥In non–strict mode, if a function is called with a this value that's not an object, the this value is substituted with an object. null and undefined become globalThis. Primitives like 7 or 'foo' are converted to an object using the related constructor, so the primitive number 7 is converted to a Number wrapper class and the string 'foo' to a String wrapper class.

js
function bar() {
  console.log(Object.prototype.toString.call(this));
}

bar.call(7); // [object Number]
bar.call("foo"); // [object String]
bar.call(undefined); // [object Window]

绑定()方法

¥The bind() method

调用 f.bind(someObject) 会创建一个与 f 具有相同主体和作用域的新函数,但 this 的值永久绑定到 bind 的第一个参数,无论该函数是如何调用的。

¥Calling f.bind(someObject) creates a new function with the same body and scope as f, but the value of this is permanently bound to the first argument of bind, regardless of how the function is being called.

js
function f() {
  return this.a;
}

const g = f.bind({ a: "azerty" });
console.log(g()); // azerty

const h = g.bind({ a: "yoo" }); // bind only works once!
console.log(h()); // azerty

const o = { a: 37, f, g, h };
console.log(o.a, o.f(), o.g(), o.h()); // 37 37 azerty azerty

箭头函数中的 this

¥this in arrow functions

箭头函数在封闭执行上下文的 this 值上创建闭包。在下面的示例中,我们使用方法 getThisGetter 创建 obj,该方法返回一个返回 this 值的函数。返回的函数被创建为箭头函数,因此其 this 永久绑定到其封闭函数的 this。可以在调用中设置 getThisGetterthis 的值,从而设置返回函数的返回值。我们假设 getThisGetter 是一个非严格函数,这意味着它包含在非严格脚本中,并且不会进一步嵌套在类或严格函数中。

¥Arrow functions create closures over the this value of the enclosing execution context. In the following example, we create obj with a method getThisGetter that returns a function that returns the value of this. The returned function is created as an arrow function, so its this is permanently bound to the this of its enclosing function. The value of this inside getThisGetter can be set in the call, which in turn sets the return value of the returned function. We will assume that getThisGetter is a non-strict function, which means it's contained in a non-strict script and not further nested in a class or strict function.

js
const obj = {
  getThisGetter() {
    const getter = () => this;
    return getter;
  },
};

我们可以将 getThisGetter 调用为 obj 的方法,在其体内将 this 绑定到 obj。返回的函数被分配给变量 fn。现在,调用 fn 时,返回的 this 的值仍然是调用 getThisGetter 时设置的值,即 obj。如果返回的函数不是箭头函数,则此类调用将导致 this 值为 globalThis,因为 getThisGetter 是非严格的。

¥We can call getThisGetter as a method of obj, which binds this to obj inside its body. The returned function is assigned to a variable fn. Now, when calling fn, the value of this returned is still the one set by the call to getThisGetter, which is obj. If the returned function was not an arrow function, such calls would cause the this value to be globalThis, because getThisGetter is non-strict.

js
const fn = obj.getThisGetter();
console.log(fn() === obj); // true

但如果你在未调用 obj 的方法的情况下解除绑定,请务必小心,因为 getThisGetter 仍然是一个具有变化的 this 值的方法。在以下示例中调用 fn2()() 将返回 globalThis,因为它遵循 fn2() 中的 this,而 fn2()globalThis,因为它是在不附加到任何对象的情况下调用的。

¥But be careful if you unbind the method of obj without calling it, because getThisGetter is still a method that has a varying this value. Calling fn2()() in the following example returns globalThis, because it follows the this from fn2(), which is globalThis since it's called without being attached to any object.

js
const fn2 = obj.getThisGetter;
console.log(fn2()() === globalThis); // true in non-strict mode

在定义回调时,此行为非常有用。通常,每个函数表达式都会创建自己的 this 绑定,该绑定会隐藏上层作用域的 this 值。现在,如果你不关心 this 值,并且只在你关心的地方创建 this 绑定(例如在类方法中),则可以将函数定义为箭头函数。参见 setTimeout() 为例

¥This behavior is very useful when defining callbacks. Usually, each function expression creates its own this binding, which shadows the this value of the upper scope. Now, you can define functions as arrow functions if you don't care about the this value, and only create this bindings where you do (e.g. in class methods). See example with setTimeout().

带有 getter 或 setter

¥this with a getter or setter

getter 和 setter 中的 this 基于访问属性的对象,而不是定义属性的对象。用作 getter 或 setter 的函数的 this 绑定到从中设置或获取属性的对象。

¥this in getters and setters is based on which object the property is accessed on, not which object the property is defined on. A function used as getter or setter has its this bound to the object from which the property is being set or gotten.

js
function sum() {
  return this.a + this.b + this.c;
}

const o = {
  a: 1,
  b: 2,
  c: 3,
  get average() {
    return (this.a + this.b + this.c) / 3;
  },
};

Object.defineProperty(o, "sum", {
  get: sum,
  enumerable: true,
  configurable: true,
});

console.log(o.average, o.sum); // 2 6

DOM 事件处理程序中的 this

¥this in DOM event handlers

当函数用作事件处理程序时,其 this 参数绑定到放置监听器的 DOM 元素(对于使用 addEventListener() 以外的方法动态添加的监听器,某些浏览器不遵循此约定)。

¥When a function is used as an event handler, its this parameter is bound to the DOM element on which the listener is placed (some browsers do not follow this convention for listeners added dynamically with methods other than addEventListener()).

js
// When called as a listener, turns the related element blue
function bluify(e) {
  // Always true
  console.log(this === e.currentTarget);
  // true when currentTarget and target are the same object
  console.log(this === e.target);
  this.style.backgroundColor = "#A5D9F3";
}

// Get a list of every element in the document
const elements = document.getElementsByTagName("*");

// Add bluify as a click listener so when the
// element is clicked on, it turns blue
for (const element of elements) {
  element.addEventListener("click", bluify, false);
}

this 在内联事件处理程序中

¥this in inline event handlers

当从内联 事件处理程序属性 调用代码时,其 this 绑定到放置监听器的 DOM 元素:

¥When the code is called from an inline event handler attribute, its this is bound to the DOM element on which the listener is placed:

html
<button onclick="alert(this.tagName.toLowerCase());">Show this</button>

上述警报显示 button。但请注意,只有外部作用域的 this 才以这种方式绑定:

¥The above alert shows button. Note, however, that only the outer scope has its this bound this way:

html
<button onclick="alert((function () { return this; })());">
  Show inner this
</button>

在这种情况下,内部函数的 this 参数绑定到 globalThis (即非严格模式下的默认对象,其中 this 不会在调用中传递)。

¥In this case, the this parameter of the inner function is bound to globalThis (i.e. the default object in non–strict mode where this isn't passed in the call).

类中的绑定方法

¥Bound methods in classes

就像常规函数一样,方法中 this 的值取决于它们的调用方式。有时,覆盖此行为很有用,以便类中的 this 始终引用类实例。要实现此目的,请在构造函数中绑定类方法:

¥Just like with regular functions, the value of this within methods depends on how they are called. Sometimes it is useful to override this behavior so that this within classes always refers to the class instance. To achieve this, bind the class methods in the constructor:

js
class Car {
  constructor() {
    // Bind sayBye but not sayHi to show the difference
    this.sayBye = this.sayBye.bind(this);
  }

  sayHi() {
    console.log(`Hello from ${this.name}`);
  }

  sayBye() {
    console.log(`Bye from ${this.name}`);
  }

  get name() {
    return "Ferrari";
  }
}

class Bird {
  get name() {
    return "Tweety";
  }
}

const car = new Car();
const bird = new Bird();

// The value of 'this' in methods depends on their caller
car.sayHi(); // Hello from Ferrari
bird.sayHi = car.sayHi;
bird.sayHi(); // Hello from Tweety

// For bound methods, 'this' doesn't depend on the caller
bird.sayBye = car.sayBye;
bird.sayBye(); // Bye from Ferrari

注意:类始终处于严格模式。如果方法尝试访问 this 上的属性,则调用未定义 this 的方法将引发错误。

¥Note: Classes are always in strict mode. Calling methods with an undefined this will throw an error if the method tries to access properties on this.

js
const carSayHi = car.sayHi;
carSayHi(); // TypeError because the 'sayHi' method tries to access 'this.name', but 'this' is undefined in strict mode.

但请注意,自动绑定方法遇到与 对类属性使用箭头函数 相同的问题:该类的每个实例都有自己的方法副本,这会增加内存使用量。仅在绝对必要时使用它。你还可以模仿 Intl.NumberFormat.prototype.format() 的实现:将属性定义为 getter,在访问时返回绑定函数并保存它,以便该函数仅创建一次并且仅在必要时创建。

¥Note, however, that auto-bound methods suffer from the same problem as using arrow functions for class properties: each instance of the class will have its own copy of the method, which increases memory usage. Only use it where absolutely necessary. You can also mimic the implementation of Intl.NumberFormat.prototype.format(): define the property as a getter that returns a bound function when accessed and saves it, so that the function is only created once and only created when necessary.

this 在 with 语句中

¥this in with statements

尽管 with 语句已被弃用并且在严格模式下不可用,但它们仍然作为正常 this 绑定规则的例外。如果在 with 语句中调用函数并且该函数是范围对象的属性,则 this 值将绑定到范围对象,就好像 obj1. 前缀存在一样。

¥Although with statements are deprecated and not available in strict mode, they still serve as an exception to the normal this binding rules. If a function is called within a with statement and that function is a property of the scope object, the this value is bound to the scope object, as if the obj1. prefix exists.

js
const obj1 = {
  foo() {
    return this;
  },
};

with (obj1) {
  console.log(foo() === obj1); // true
}

规范

Specification
ECMAScript Language Specification
# sec-this-keyword

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看