jQuery 类方法中的打字稿“this”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16157839/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Typescript "this" inside a class method
提问by Clark
I know this is probably painfully basic, but i am having a tough time wrapping my head around it.
我知道这可能是非常基本的,但我很难理解它。
class Main
{
constructor()
{
requestAnimationFrame(this.update); //fine
}
update(): void
{
requestAnimationFrame(this.update); //error, because this is window
}
}
It appears to be the case that I need a proxy, so lets say using Jquery
我似乎需要一个代理,所以可以说使用 Jquery
class Main
{
constructor()
{
this.updateProxy = $.proxy(this.update, this);
requestAnimationFrame(this.updateProxy); //fine
}
updateProxy: () => void
update(): void
{
requestAnimationFrame(this.updateProxy); //fine
}
}
But coming from an Actionscript 3 background, I am not really sure what is happening here. Sorry I am not sure where Javascript begins and TypeScript ends.
但是来自 Actionscript 3 的背景,我不太确定这里发生了什么。抱歉,我不确定 Javascript 从哪里开始,TypeScript 在哪里结束。
updateProxy: () => void
And also, I am not convinced I am doing this right. The last thing I want is most of my class having a a() function which needs to be accessed with aProxy()
as I feel I am writing the same thing twice? Is it normal?
而且,我不相信我这样做是正确的。我想要的最后一件事是我的大部分班级都有 aa() 函数需要访问,aProxy()
因为我觉得我在写同样的东西两次?正常吗?
回答by basarat
If you want this
captured the TypeScript way of doing this is via arrow functions. To quote Anders:
如果你想this
捕获 TypeScript 这样做的方法是通过箭头函数。引用安德斯的话:
The
this
in arrow functions is lexically scoped
在
this
沿箭头功能的词法作用域
Here is the way I like to use this to my advantage:
这是我喜欢利用它来发挥我的优势的方式:
class test{
// Use arrow functions
func1=(arg:string)=>{
return arg+" yeah" + this.prop;
}
func2=(arg:number)=>{
return arg+10 + this.prop;
}
// some property on this
prop = 10;
}
View this in the TypeScript Playground
You can see that in the generated JavaScript this
is captured outsidethe function call:
可以看到在生成的 JavaScriptthis
是在函数调用之外捕获的:
var _this = this;
this.prop = 10;
this.func1 = function (arg) {
return arg + " yeah" + _this.prop;
};
so the this
value inside the function call (which could be window
) would not be used.
因此不会使用this
函数调用中的值(可能是window
)。
To learn more: “Understanding this
in TypeScript” (4:05) – YouTube
回答by joelnet
If you write your methods like this, 'this' will be treated the way you expect.
如果您像这样编写方法,“this”将按照您期望的方式处理。
class Main
{
constructor()
{
requestAnimationFrame(() => this.update());
}
update(): void
{
requestAnimationFrame(() => this.update());
}
}
Another option would be to bind 'this' to the function call:
另一种选择是将“this”绑定到函数调用:
class Main
{
constructor()
{
requestAnimationFrame(this.update.bind(this));
}
update(): void
{
requestAnimationFrame(this.update.bind(this));
}
}
回答by Simon_Weaver
See page 72 of the typescript language specification https://github.com/Microsoft/TypeScript/blob/master/doc/TypeScript%20Language%20Specification.pdf?raw=true
请参阅打字稿语言规范的第 72 页 https://github.com/Microsoft/TypeScript/blob/master/doc/TypeScript%20Language%20Specification.pdf?raw=true
Arrow Function Expressions
箭头函数表达式
In the example
在示例中
class Messenger {
message = "Hello World";
start() {
setTimeout(() => alert(this.message), 3000);
}
};
var messenger = new Messenger();
messenger.start();
the use of an arrow function expression causes the callback to have the same this as the surrounding ‘start' method. Writing the callback as a standard function expression it becomes necessary to manually arrange access to the surrounding this, for example by copying it into a local variable:
箭头函数表达式的使用导致回调与周围的“start”方法具有相同的 this 。将回调编写为标准函数表达式,因此必须手动安排对周围 this 的访问,例如通过将其复制到局部变量中:
This is the actual generated Javascript:
这是实际生成的 Javascript:
class Messenger {
message = "Hello World";
start() {
var _this = this;
setTimeout(function() { alert(_this.message); }, 3000);
}
};
回答by Peter Morris
The problem arises when you pass a function as a callback. By the time the callback has executed the value of "this" could have changed to the Window, the control invoking the callback, or something else.
当您将函数作为回调传递时,就会出现问题。到回调执行时,“this”的值可能已更改为 Window、调用回调的控件或其他内容。
Make sure you always use a lambda expression at the point you pass a reference to the function to be called back. For example
确保在传递对要回调的函数的引用时始终使用 lambda 表达式。例如
public addFile(file) {
this.files.push(file);
}
//Not like this
someObject.doSomething(addFile);
//but instead, like this
someObject.doSomething( (file) => addFile(file) );
This compiles to something like
这编译成类似的东西
this.addFile(file) {
this.files.push(file);
}
var _this = this;
someObject.doSomething(_this.addFile);
Because the addFile function is being called on a specific object reference (_this) it does not use the "this" of the invoker but instead the value of _this.
因为 addFile 函数是在特定对象引用 (_this) 上调用的,所以它不使用调用者的“this”,而是使用 _this 的值。
回答by Karim Ayachi
Very late to the party, but I think it is very important for future visitors of this question to consider the following:
聚会很晚,但我认为对于这个问题的未来访问者来说,考虑以下几点非常重要:
The other answers, including the accepted one, miss a crucial point:
其他答案,包括被接受的答案,都忽略了一个关键点:
myFunction() { ... }
and
和
myFunction = () => { ... }
are notthe same thing "with the exception that the latter captures this
".
是不一样的东西“不同的是后者捕获this
”。
The first syntax creates a method on the prototype, while the second syntax creates a property on the object whos value is a function (that also happens to capture this
). You can see this clearly in the transpiled JavaScript.
第一个语法在原型上创建一个方法,而第二个语法在对象上创建一个属性,该属性的值是一个函数(也恰好是 capture this
)。您可以在转译的 JavaScript 中清楚地看到这一点。
To be complete:
要完整:
myFunction = function() { ... }
would be the same als the second syntax, but without the capturing.
与第二个语法相同,但没有捕获。
So, using the arrow syntax in most caseswill fix your problem of binding to the object, but it's not the same and there are many situations where you do want to have a proper function on the prototype in stead of a property.
因此,在大多数情况下使用箭头语法将解决您绑定到对象的问题,但情况并非如此,并且在许多情况下,您确实希望在原型上拥有适当的函数而不是属性。
In these cases using a proxy or .bind()
actually isthe correct solution. (Although suffering readability.)
在这些情况下,使用代理或.bind()
实际上是正确的解决方案。(虽然可读性差。)
More reading here (not primarily about TypeScript, but the principles stand):
在这里阅读更多(主要不是关于 TypeScript,而是原则):
https://ponyfoo.com/articles/binding-methods-to-class-instance-objects
https://ponyfoo.com/articles/binding-methods-to-class-instance-objects
回答by Kenneth
In short, the this keyword always has a reference to the object that called the function.
简而言之,this 关键字始终引用调用该函数的对象。
In Javascript, since functions are just variables, you can pass them around.
在 Javascript 中,由于函数只是变量,您可以传递它们。
Example:
例子:
var x = {
localvar: 5,
test: function(){
alert(this.localvar);
}
};
x.test() // outputs 5
var y;
y.somemethod = x.test; // assign the function test from x to the 'property' somemethod on y
y.test(); // outputs undefined, this now points to y and y has no localvar
y.localvar = "super dooper string";
y.test(); // outputs super dooper string
When you do the following with jQuery:
当您使用 jQuery 执行以下操作时:
$.proxy(this.update, this);
What you are doing is overriding that context. Behind the scenes jQuery will guive you this:
您正在做的是覆盖该上下文。在幕后,jQuery 会告诉你:
$.proxy = function(fnc, scope){
return function(){
return fnc.apply(scope); // apply is a method on a function that calls that function with a given this value
}
};
回答by Maxter
How about doing it this way? Declare a global variable of type "myClass" and initialise it in the constructor of the class:
这样做怎么样?声明一个“myClass”类型的全局变量并在类的构造函数中初始化它:
var _self: myClass;
class myClass {
classScopeVar: string = "hello";
constructor() {
_self = this;
}
alerter() {
setTimeout(function () {
alert(_self.classScopeVar)
}, 500);
}
}
var classInstance = new myClass();
classInstance.alerter();
Note: It is important NOT to use "self" as it as a special meaning already.
注意:重要的是不要将“self”用作特殊含义。