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
语法
值
描述
函数上下文
¥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:
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.
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:
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.
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.
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
设置为undefined
或null
,则this
将替换为globalThis
。 - 如果调用该函数时将
this
设置为原始值,则this
将替换为原始值的封装对象。
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 的实现者确定。回调通常使用 this
值 undefined
进行调用(直接调用它而不将其附加到任何对象),这意味着如果函数是非严格的,则 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.
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.
[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:
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.
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.
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
函数内部的 this
与 super.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 可以分为两个上下文:静态和实例。构造函数、方法和实例字段初始值设定项(public 或 private)属于实例上下文。静止的 方法、静态字段初始值设定项和 静态初始化块 属于静态上下文。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.
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:
this = new Base();
警告:在调用
super()
之前引用this
会引发错误。¥Warning: Referring to
this
before callingsuper()
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.
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 toglobalThis
makes them global variables) — this is the case for browsers and Node — but hosts are allowed to provide a different value forglobalThis
that's unrelated to the global object.
// 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.
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.exports
的 this
值执行。事件处理程序属性 执行时将 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.
const obj = {
a: this,
};
console.log(obj.a === window); // true
示例
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.
// 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.
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
值将替换为对象。null
和 undefined
变成 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.
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.
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
。可以在调用中设置 getThisGetter
内 this
的值,从而设置返回函数的返回值。我们假设 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.
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.
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.
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.
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()
).
// 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:
<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:
<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:
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 onthis
.jsconst 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.
const obj1 = {
foo() {
return this;
},
};
with (obj1) {
console.log(foo() === obj1); // true
}
规范
Specification |
---|
ECMAScript Language Specification # sec-this-keyword |
浏览器兼容性
BCD tables only load in the browser
也可以看看
¥See also