[英]What is the difference between class method vs. class field function vs. class field arrow function?
What is the difference between class method, class property which is a function, and class property which is an arrow function?类方法、作为函数的类属性和作为箭头函数的类属性有什么区别? Does the
this
keyword behave differently in the different variants of the method? this
关键字在方法的不同变体中的行为是否不同?
class Greeter {
constructor() {
this.greet();
this.greet2();
this.greet3();
}
greet() {
console.log('greet1', this);
}
greet2 = () => {
console.log('greet2', this);
}
greet3 = function() {
console.log('greet3', this);
}
}
let bla = new Greeter();
This is the resulting JavaScript when transpiled from TypeScript.这是从 TypeScript 转译的结果 JavaScript。
var Greeter = /** @class */ (function () {
function Greeter() {
var _this = this;
this.greet2 = function () {
console.log('greet2', _this);
};
this.greet3 = function () {
console.log('greet3', this);
};
this.greet();
this.greet2();
this.greet3();
}
Greeter.prototype.greet = function () {
console.log('greet1', this);
};
return Greeter;
}());
var bla = new Greeter();
My TypeScript version is 3.4.5.我的 TypeScript 版本是 3.4.5。
There are differences between all 3 versions.所有 3 个版本之间都存在差异。 This differences are in 3 areas:
这种差异体现在 3 个方面:
this
at runtimethis
是谁this
in typescript.this
的类型是什么。 Lets start with where they work just the same.让我们从它们工作的地方开始。 Consider this class, with a class field:
考虑这个具有类字段的类:
class Greeter {
constructor(private x: string) {
}
greet() {
console.log('greet1', this.x);
}
greet2 = () => {
console.log('greet2', this.x);
}
greet3 = function () {
// this is typed as any
console.log('greet3', this.x);
}
}
let bla = new Greeter(" me");
With this class all 3 function calls will print as expected: 'greet* me'
when invoked on bla
有了这个类,所有 3 个函数调用都将按预期打印:在
bla
调用时, 'greet* me'
bla.greet()
bla.greet2()
bla.greet3()
Who is this at runtime运行时这是谁
Arrow functions capture this
from the declaration context, so this
in greet2
is always guaranteed to be the class instance that created this function.箭头功能捕捉
this
从声明上下文,所以this
在greet2
始终保证是创建此函数的类的实例。 The other versions (the method and function) make no such guarantees.其他版本(方法和函数)没有这样的保证。
So in this code not all 3 print the same text:因此,在此代码中,并非所有 3 个都打印相同的文本:
function call(fn: () => void) {
fn();
}
call(bla.greet) // greet1 undefined
call(bla.greet2) //greet2 me
call(bla.greet3) // greet3 undefined
This is particularly important when passing the function as an event handler to another component.这在将函数作为事件处理程序传递给另一个组件时尤为重要。
Where the function is assigned分配功能的地方
Class methods (such as greet
) are assigned on the prototype, field initializations (such as greet2
and greet3
) are assigned in the constructor.类方法(如
greet
)在原型上赋值,字段初始化(如greet2
和greet3
)在构造函数中赋值。 This means that greet2
and greet3
will have a larger memory footprint as they require an allocation of a fresh closure each time Greeter
is instantiated.这意味着
greet2
和greet3
将有更大的内存占用,因为它们需要在每次Greeter
实例化时分配一个新的闭包。
What is the type of this in typescript.打字稿中 this 的类型是什么。
Typescript will type this
as an instance of Greeter
in both the method ( greet
) and the arrow function ( greet2
) but will type this
as any in greet3
.打字稿将键入
this
作为实例Greeter
在方法(两者greet
)和箭头功能( greet2
),但将输入this
作为任何在greet3
。 This will make it an error if you try to use this
in greet3
under noImplictAny
这将使一个错误,如果你尝试使用
this
在greet3
下noImplictAny
When to use them何时使用它们
Use the method syntax if this function will not be passed as an event handler to another component (unless you use bind
or something else to ensure this
remains the instance of the class)如果此函数不会作为事件处理程序传递给另一个组件,请使用方法语法(除非您使用
bind
或其他方法来确保this
仍然是类的实例)
Use arrow function syntax when your function will be passed around to other components and you need access to this
inside the function.当您的函数将传递给其他组件并且您需要在函数内部访问
this
时,请使用箭头函数语法。
Can't really think of a good use case for this, generally avoid.真的想不出一个好的用例,一般避免。
this
keyword difference: this
关键字区别: In the above all three have same this
but you will see the difference when you will pass the method to another functions.在上面所有三个都有相同的
this
但是当你将方法传递给另一个函数时你会看到不同。
class Greeter { constructor() { } greet() { console.log(this); } greet2 = () => { console.log(this); } greet3 = function() { console.log(this); } } let bla = new Greeter(); function wrapper(f){ f(); } wrapper(bla.greet) //undefined wrapper(bla.greet2) //Greeter wrapper(bla.greet3) //undefined
But there is another difference that the first method is on the prototype
of class
while other two are not.但是还有一个区别,第一个方法在
class
的prototype
,而其他两个不在。 They are the method of instance of object.它们是对象实例的方法。
class Greeter { constructor() { } greet() { console.log('greet1', this); } greet2 = () => { console.log('greet2', this); } greet3 = function() { console.log('greet3', this); } } let bla = new Greeter(); console.log(Object.getOwnPropertyNames(Greeter.prototype))
If I have in the class ->
str = "my string";
如果我在课堂上 ->
str = "my string";
and in all the 3 methods I can sayconsole.log(this.str)
and it outputs the "my string".在所有 3 种方法中,我都可以说
console.log(this.str)
并输出“我的字符串”。 But I wonder - is this really actually the same thing但我想知道 - 这真的是同一件事吗
No they are not same things.不,它们不是同一回事。 As I mentioned that
greet2
and greet3
will not be on Greeter.prototype
instead they will be on the instance itself.正如我提到的,
greet2
和greet3
不会在Greeter.prototype
而是在实例本身上。 It mean that if you create 1000
instances of Greeter
their will be 1000 different method( greet2
and greet3
) stored in memory for 1000 different instances.这意味着如果你创建
1000
Greeter
实例,它们将有 1000 个不同的方法( greet2
和greet3
)存储在内存中,用于 1000 个不同的实例。 But there will a single greet
method for all the instances.但是所有实例都有一个
greet
方法。
See the below snippet with two instances of Greeter()
请参阅下面的代码片段,其中包含两个
Greeter()
实例
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.