Typescript中的类方法与属性函数与属性箭头函数之间有什么区别? [英] What is the difference between class method vs property function vs property arrow function in typescript?
问题描述
我想知道-类方法,作为函数的类属性和作为箭头函数的类属性之间有什么区别?在不同的方法变体中,"this"关键字的行为是否有所不同?
I was wondering - 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?
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();
已编译打字稿的javascript输出:
javascript output from the compiled typescript:
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();
我的TypeScript版本是3.4.5
My TypeScript version is 3.4.5
推荐答案
所有3个版本之间都存在差异.区别在于3个方面:
There are differences between all 3 versions. This differences are in 3 areas:
- 运行时
this
是谁 - 分配功能的地方
- 打字稿中
的类型是什么.
- Who is
this
at runtime - Where the function is assigned
- What is the type of
this
in typescript.
让我们从它们在相同的地方开始.考虑带有一个类字段的此类:
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");
使用此类,所有3个函数调用将按预期打印:'greet* me'
在bla
With this class all 3 function calls will print as expected: 'greet* me'
when invoked on bla
bla.greet()
bla.greet2()
bla.greet3()
运行时是谁
箭头函数从声明上下文中捕获this
,因此始终保证greet2
中的this
是创建此函数的类实例.其他版本(方法和功能)不提供此类保证.
Arrow functions capture this
from the declaration context, so this
in greet2
is always guaranteed to be the class instance that created this function. The other versions (the method and function) make no such guarantees.
因此在此代码中,并非所有3个都打印相同的文本:
So in this code not all 3 print the same text:
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.
分配功能的地方
Class方法(例如greet
),在构造函数中分配了字段初始化(例如greet2
和greet3
).这意味着greet2
和greet3
将具有更大的内存占用空间,因为每次实例化Greeter
时,它们都需要分配一个新的闭包.
Class methods (such as greet
) are assigned on the prototype, field initializations (such as greet2
and greet3
) are assigned in the constructor. 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.
打字稿中的此类型是什么.
Typescript在方法(greet
)和箭头函数(greet2
)中都将this
作为Greeter
的实例,但是将在greet3
中键入this
.如果您尝试在noImplictAny
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 will make it an error if you try to use this
in greet3
under noImplictAny
何时使用它们
-
如果该函数不会作为事件处理程序传递给另一个组件,请使用方法语法(除非您使用
bind
或其他方法来确保this
仍是该类的实例)
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 ensurethis
remains the instance of the class)
当您的函数将被传递给其他组件并且需要访问函数内部的this
时,请使用箭头函数语法.
Use arrow function syntax when your function will be passed around to other components and you need access to this
inside the function.
为此,真的不能想到一个好的用例,通常避免使用.
Can't really think of a good use case for this, generally avoid.
这篇关于Typescript中的类方法与属性函数与属性箭头函数之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!