class Aa {
methodA() {
console.log('welcome to method a')
}
methodB() {
console.log('welcome to method b')
// methodA() // Fails!! Uncaught ReferenceError: methodA is not defined
this.methodA() // Works because of this.
}
}
let myclass = new Aa()
myclass.methodB()
Run Code Online (Sandbox Code Playgroud)
简洁地解释为什么在调用您已经使用的类的另一个方法时需要使用“this”的最佳方法是什么?
直觉可能会说,好吧,如果 JS 知道我正在使用一个类的方法,那么它就知道那个类......因为我正在使用它的方法......那么为什么它不能找到另一个方法没有我告诉它的同一个类......是的'这个'同一个地方!
相比之下,函数可以毫无问题地做到这一点:
function a() {
console.log('welcome to function a')
}
function b() {
console.log('welcome to function b')
a() // works without any sort of 'scope help'
}
b()
Run Code Online (Sandbox Code Playgroud)
我希望能够解释它,而不会让人们分心,需要知道它的最深层原因。如果可以的话,哈!
我的一部分只是想说,“这就是 JS 类的工作方式。你必须'这个' - 化事情。”
为了理解为什么我们需要this在 Javascript 类中显式引用,我们首先需要了解this引用在普通函数中指向什么。
在 Javascript 中,this关键字始终是对调用函数的对象的引用。
考虑以下:
const obj1 = {
foo() { console.log(this); }
}
obj1.foo(); // "this" will reference "obj1"Run Code Online (Sandbox Code Playgroud)
这里没什么奇怪的,this就是对定义它的对象的引用obj1。
现在想想如果我们获取函数foo并将其从对象中“删除”会发生什么。既然this是对调用该函数的对象的引用,那么this如果该函数不属于某个对象呢?
const obj1 = {
foo() { console.log(this); }
}
const foo = obj1.foo;
foo(); // "this" will reference "window"Run Code Online (Sandbox Code Playgroud)
这被人开始变得奇怪了,this实际上是对global对象的引用。这是因为 Javascript 中的一切都是对象,甚至是文件的根级别。在浏览器中,这个全局对象称为window对象。
现在考虑如果我们将方法重新附加到另一个对象会发生什么?
const obj1 = {
foo() { console.log(this); }
}
const foo = obj1.foo;
const obj2 = {};
obj2.foo = foo;
obj2.foo(); // "this" will reference "obj2"Run Code Online (Sandbox Code Playgroud)
此处适用相同的规则,因为函数现在再次属于this引用指向的对象obj2。
所有 Javascript 中的第一个实际上没有类。js 类只是以不同的方式编写原型。
让我们从编写一个简单的类开始。
class Foo {
constructor() { console.log("I'm a Class constructor") }
log() { console.log("I'm a Class method") }
}
const obj1 = new Foo(); // I'm a Class constructor
obj1.log(); // I'm a Class method Run Code Online (Sandbox Code Playgroud)
现在让我们编写与原型相同的“类”。
function Bar() {
console.log("I'm a Prototype constructor")
}
Bar.prototype = {
log() {
console.log("I'm a Prototype method")
}
}
const obj2 = new Bar(); // I'm a Prototype constructor
obj2.log(); // I'm a Prototype methodRun Code Online (Sandbox Code Playgroud)
这两种编写继承(类和原型)的方式在 Javascript 中是一回事。
因此,我们可以在原型实现中更清楚地看到,“类方法”实际上只是一个分配给函数原型的对象。
现在我们知道了this,classes / prototypes我们可以看到类方法实际上只是一个对象上的函数,它this指的是调用该函数的对象。所以如果我们想在同一个对象上引用另一个函数,我们应该通过引用来引用它this。
class Aa {
methodA() {
console.log('welcome to method a')
}
methodB() {
console.log('welcome to method b')
this.methodA()
}
}
const myclass = new Aa()
myclass.methodB()Run Code Online (Sandbox Code Playgroud)
之所以令人困惑,主要是因为 Javascript 长期以来一直试图将原型的方钉装入类的圆孔中。很多在传统面向对象语言中有意义的事情只会导致 JavaScript 中的混乱。
你的(非常合理的)直觉在这里偏离了轨道:
直觉可能会说,如果 JS 知道我正在使用类的方法,那么它就知道该类......因为我正在使用它的方法
methodA()并且methodA()只是函数。他们不知道自己的定义在哪里。他们所知道的是他们是如何被称呼的。 this是将函数的调用方式与类的其余部分联系起来的关键。考虑这个例子:
class Aa {
methodA() {console.log('welcome to method a')}
methodB() {
console.log('welcome to method b')
this.methodA() // Works because of this.
}
}
let obj = {
methodA() { console.log("welcome to imposter A")}
}
let myclass = new Aa()
obj.methodB = myclass.methodB // take a reference to methodB and add it a different obj
console.log("Same?",obj.methodB === myclass.methodB)
// identical function but it has no idea
// it "belongs" to myclass. Called from a different context
// it acts like a normal function (because it is)
obj.methodB() Run Code Online (Sandbox Code Playgroud)
该函数obj.methodB不知道它属于class Aa. 它与类的唯一联系是它的调用方式,而它的调用方式决定了 的值this。所以this(和原型链)是将整个方案粘合在一起的粘合剂。
| 归档时间: |
|
| 查看次数: |
1095 次 |
| 最近记录: |