this
is a keyword that has different values depending on where it’s used.
this
是一个根据其使用位置而具有不同值的关键字。
Not knowing this tiny detail of JavaScript can cause a lot of headaches, so it’s worth taking 5 minutes to learn all the tricks.
不知道JavaScript的微小细节会引起很多麻烦,因此值得花5分钟来学习所有技巧。
this
在严格模式 (this
in strict mode)
Outside any object, this
in strict mode is always undefined
.
在任何对象之外, 严格模式下的 this
对象始终是undefined
。
Notice I mentioned strict mode. If strict mode is disabled (the default state if you don’t explicitly add 'use strict'
on top of your file ), you are in the so-called sloppy mode, and this
- unless some specific cases mentioned here below - has the value of the global object.
注意,我提到了严格模式。 如果禁用了严格模式(默认状态,如果您未在文件顶部显式添加'use strict'
),则您处于所谓的草率模式 ,除非下面提到的某些特定情况,否则this
模式具有全局对象的值。
Which means window
in a browser context.
这表示浏览器上下文中的window
。
this
方法 (this
in methods)
A method is a function attached to an object.
方法是附加到对象的功能。
You can see it in various forms.
您可以以各种形式查看它。
Here’s one:
这是一个:
const car = {
maker: 'Ford',
model: 'Fiesta',
drive() {
console.log(`Driving a ${this.maker} ${this.model} car!`)
}
}
car.drive()
//Driving a Ford Fiesta car!
In this case, using a regular function, this
is automatically bound to the object.
在这种情况下,使用常规函数this
其自动绑定到对象。
Note: the above method declaration is the same as drive: function() {
…, but shorter:
注意:上面的方法声明与drive: function() {
…相同,但更短:
const car = {
maker: 'Ford',
model: 'Fiesta',
drive: function() {
console.log(`Driving a ${this.maker} ${this.model} car!`)
}
}
The same works in this example:
在此示例中,同样的工作原理:
const car = {
maker: 'Ford',
model: 'Fiesta'
}
car.drive = function() {
console.log(`Driving a ${this.maker} ${this.model} car!`)
}
car.drive()
//Driving a Ford Fiesta car!
An arrow function does not work in the same way, as it’s lexically bound:
箭头函数与按词法绑定的工作方式不同:
const car = {
maker: 'Ford',
model: 'Fiesta',
drive: () => {
console.log(`Driving a ${this.maker} ${this.model} car!`)
}
}
car.drive()
//Driving a undefined undefined car!
绑定箭头功能 (Binding arrow functions)
You cannot bind a value to an arrow function, like you do with normal functions.
您不能像使用普通函数那样将值绑定到箭头函数。
It’s not possible due to the way they work. this
is lexically bound, which means its value is derived from the context where they are defined.
由于它们的工作方式,这是不可能的。 this
是按词法绑定的 ,这意味着其值是从定义它们的上下文中派生的。
明确传递要用作this
对象的对象 (Explicitly pass an object to be used as this
)
JavaScript offers a few ways to map this
to any object you want.
JavaScript的提供了一些方法来映射this
你想要的任何对象。
Using bind()
, at the function declaration step:
在函数声明步骤中使用bind()
:
const car = {
maker: 'Ford',
model: 'Fiesta'
}
const drive = function() {
console.log(`Driving a ${this.maker} ${this.model} car!`)
}.bind(car)
drive()
//Driving a Ford Fiesta car!
You could also bind an existing object method to remap its this
value:
您还可以绑定现有的对象方法以重新映射其this
值:
const car = {
maker: 'Ford',
model: 'Fiesta',
drive() {
console.log(`Driving a ${this.maker} ${this.model} car!`)
}
}
const anotherCar = {
maker: 'Audi',
model: 'A4'
}
car.drive.bind(anotherCar)()
//Driving a Audi A4 car!
Using call()
or apply()
, at the function invocation step:
在函数调用步骤中使用call()
或apply()
:
const car = {
maker: 'Ford',
model: 'Fiesta'
}
const drive = function(kmh) {
console.log(`Driving a ${this.maker} ${this.model} car at ${kmh} km/h!`)
}
drive.call(car, 100)
//Driving a Ford Fiesta car at 100 km/h!
drive.apply(car, [100])
//Driving a Ford Fiesta car at 100 km/h!
The first parameter you pass to call()
or apply()
is always bound to this
. The difference between call() and apply() is just that the second one wants an array as the arguments list, while the first accepts a variable number of parameters, which passes as function arguments.
您传递给call()
或apply()
的第一个参数始终绑定到this
。 call()和apply()之间的区别只是第二个要使用数组作为参数列表,而第一个要接受可变数量的参数,这些参数作为函数参数传递。
浏览器事件处理程序的特殊情况 (The special case of browser event handlers)
In event handlers callbacks, this
refers to the HTML element that received the event:
在事件处理程序回调中, this
是指接收事件HTML元素:
document.querySelector('#button').addEventListener('click', function(e) {
console.log(this) //HTMLElement
}
You can bind it using
您可以使用绑定
document.querySelector('#button').addEventListener(
'click',
function(e) {
console.log(this) //Window if global, or your context
}.bind(this)
)