基础知识-为什么选择“这”?(The basics — Why ‘this’?)
Just skip this if you already know. I hope I warned you that there could be confusion with the word this.
如果您已经知道,请跳过此步骤。 我希望我警告你,有可能是字这种混乱。
Let’s build a class. This would lead to an error:
让我们建立一个类。 这将导致错误:
class Car {
drive() {
console.log(“driving”, speed, “fast”)
}
}const blueCar = new Car()blueCar.speed = “120 mph”
blueCar.drive()
速度将无法定义。 为什么? (Speed would not be defined. Why?)
Because by default, the speed we want to use in the drive method searches outside for this variable. To show this, here is an example where no error occurs:
因为默认情况下,我们要在drive方法中使用的速度在外部搜索此变量。 为了说明这一点,这是一个没有错误发生的示例:
let speed = "160 mph"
class Car {
drive() {
console.log(“driving”, speed, “fast”)
}
}const blueCar = new Car()blueCar.speed = “120 mph”
blueCar.drive()
“driving 160 mph fast” will be printed, since speed refers to the variable outside of the class.
由于速度是指课外的变量,因此将打印“快速以160 mph的速度行驶”。
So if we only want to address something within our class, we will not get very far. That’s what the this-keyword is for. It always refers to the object it belongs to — in our example, the class.
因此,如果我们只想在班级中解决某些问题,那么我们就不会走得太远。 这就是这个关键字的目的。 它总是引用它所属的对象-在我们的示例中是类。
As you can see in the example below, we can also set the property for a class afterward. All these properties we assign will then be stored in this:
如您在下面的示例中看到的,我们也可以在之后为一个类设置属性。 我们分配的所有这些属性将存储在以下位置:
class Car {
drive() {
console.log(this) // Car { speed: "120 mph" }
console.log(“driving”, this.speed, “fast”)
}
}const blueCar = new Car()blueCar.speed = “120 mph”
blueCar.drive()
构造函数的作用 (The role of the constructor)
The constructor is a function that any class can have — it must be called the same, and is always executed when we create a new instance — i.e., when the class is used.
构造函数是任何类都可以拥有的函数-必须将其称为相同函数,并且在创建新实例时即始终执行该函数(即,使用该类时)。
As the name suggests, it is responsible for constructing our class. Through the constructor, we can assign values, which we can then access the this-keyword.
顾名思义,它负责构造我们的课程。 通过构造函数,我们可以分配值,然后可以访问this-keyword。
In the end, the constructor is just a function, which gets parameters and can process them.
最后,构造函数只是一个函数,它获取参数并可以对其进行处理。
class Car {
constructor(speed) {
console.log(speed) // 120 mph} drive() {
console.log("driving", speed, "fast")
}
}const blueCar = new Car("120 mph")
blueCar.drive()
The code above will lead to an error — in the drive-method, speed is not defined.
上面的代码将导致错误-在驱动方法中,速度未定义。
It is the same problem as before. Just because we now have a constructor, it does not change the fact that the searched variable is searched outside the class.
这是和以前一样的问题。 仅仅因为我们现在有了一个构造函数,它并没有改变搜索变量是在类外部搜索的事实。
But thanks to the constructor, we can use our this to set a validity within the class:
但是感谢构造函数,我们可以使用this来设置类中的有效性:
class Car {
constructor(speed) {
this.speed = speed
}
drive() {
console.log(“driving”, this.speed, “fast”)
}
}
Let’s learn more about the this-keyword now.
现在让我们更多地了解此关键字。
问题-“这个”迷路了 (Problems — ‘this’ getting lost)
Now I will show you something that looks very strange at first sight.
现在,我将向您展示乍一看非常奇怪的东西。
This will be our class again:
这将再次是我们的课:
class Car {
constructor(speed) {
this.speed = speed
}
drive() {
console.log(this.speed)
}
}
Let’s create a new instance and execute the drive-method of it:
让我们创建一个新实例并执行它的驱动方法:
const mercedes = new Car(120)
mercedes.drive() // 120 - as expected
Everything as expected. We pass something into the constructor, the constructor function binds it to the this, and of course, the drive-method can access the speed now.
一切都如预期。 我们将某些东西传递给构造函数,构造函数将其绑定到this ,当然,驱动方法现在可以访问速度了。
Here is a second way of executing the drive-method for printing our speed:
这是执行驱动方法以打印速度的第二种方法:
const driveMethod = mercedes.drive
driveMethod() // error - this.speed is not defined
An error will occur. This is a completely correct syntax, which we can use everywhere — but there is a problem with classes.
将会发生错误。 这是一种完全正确的语法,我们可以在任何地方使用它-但是类存在问题。
The function is executed, but this is lost — because this is what is in front of the dot — if we call only the function, it will be lost. Yeah, that’s weird.
该功能被执行,但这种损失-因为这是在点的前面-如果我们只调用的功能,它会丢失。 是的,那很奇怪。
更多问题-与窗口对象崩溃 (More Problems — collapsing with the window-object)
As already mentioned, this always refers to the object it is surrounded by / to which it belongs. This can become a problem; let’s look at an example:
如前所述,它始终是指被它所属的对象包围的对象。 这可能会成为一个问题; 让我们看一个例子:
class Car {
constructor(speed) {
this.speed = speed
} drive() {
console.log(“driving”, this.speed, “fast”)
setTimeout(function() { }, 1000)
}
}const blueCar = new Car(“120 mph”)blueCar.drive()
The code above works fine. But when we put the console.log into the setTimeout(), like this below, we will get an error:
上面的代码工作正常。 但是,当我们将console.log放入setTimeout()时,如下所示,我们将收到错误消息:
drive() {
setTimeout(function() {
console.log(“driving”, this.speed, “fast”)
}, 1000)
}
this.speed is undefined. Because window does not provide a speed.
this.speed是不确定的。 因为窗口不提供速度。
setTimeout belongs to the global window object. We could instead write window.setTimeout() — this now refers to the window-object.
setTimeout属于全局窗口对象。 我们可以改写window.setTimeout()-现在引用窗口对象。
That is, of course, a problem — again our this is almost lost. But there are two different workarounds. Let’s start with the one that is now considered redundant:
当然,这就是一个问题-我们的问题又几乎消失了。 但是有两种不同的解决方法。 让我们从现在被认为是多余的一个开始:
We can make a copy of the correct this.
我们可以制作一份正确的副本。
drive() {
let _this = this
setTimeout(function() {
console.log(“driving”, _this.speed, “fast”)
}, 1000)
}
This works wonderfully, but there is a more modern way. Maybe you’ve heard of Arrow Functions.
这很棒,但是还有一种更现代的方式。 也许您听说过箭头功能。
Arrow与常规功能-使用“ this”示例 (Arrow vs. regular functions — using the ‘this’-example)
Arrow Functions and regular/classic functions have some differences. One important one is how you deal with this.
箭头函数和常规/经典函数有一些区别。 一个重要的问题是您如何处理此问题。
In Arrow functions, this always represents the object that defines the Arrow function, therefore this has the original meaning from the enclosing context — in our example, our drive-method.
在Arrow函数中,它始终代表定义Arrow函数的对象,因此,它具有封闭上下文的原始含义-在我们的示例中是我们的驱动方法。
Here is an example:
这是一个例子:
drive() {
setTimeout(() => {
console.log(“driving”, this.speed, “fast”)
}, 1000)
}
This now works without any errors.
现在可以正常工作了,没有任何错误。
Here is more on arrow functions in JavaScript:
这是有关JavaScript中箭头功能的更多信息:
全球范围内的“这个” (‘this’ in the global scope)
Basically, in JavaScript, it is the case that this refers to the top-level object by default. In the browser, it is the window object, which is the origin of almost every object in JavaScript. Not only document but also e.g. Math.
基本上,在JavaScript中,默认情况下是指顶级对象。 在浏览器中,它是窗口对象,它是JavaScript中几乎每个对象的来源。 不仅文档,而且例如数学。
window.document // #documentwindow.Math.PI // 3.141….
So in JavaScript, it is the window object. However, there is no browser window in Node.js, so there is no window object — the highest object is called global.
因此在JavaScript中,它是window对象。 但是,Node.js中没有浏览器窗口,因此没有窗口对象-最高的对象称为global 。
If you open the Node.js command line and type this, you will see the following:
如果您打开Node.js命令行并键入它,您将看到以下内容:
You can access the global object also via the following ways:
您还可以通过以下方式访问全局对象:
Nevertheless, there is an intersection, of course: In the browser, setTimeout is a child of the window object; in Node.js, the setTimeout function goes to the global object.
不过,当然有一个交叉点:在浏览器中, setTimeout是window对象的子对象; 在Node.js中, setTimeout函数转到全局对象。
普通英语JavaScript(JavaScript In Plain English)
Enjoyed this article? If so, get more similar content by subscribing to Decoded, our YouTube channel!
喜欢这篇文章吗? 如果是这样,请订阅我们的YouTube频道解码,以获得更多类似的内容!
翻译自: https://medium.com/javascript-in-plain-english/this-javascript-bca2b028e5ac