在类方法中打字"this"

Cla*_*ark 75 jquery proxy-classes this typescript

我知道这可能是基本的痛苦,但我很难绕过它.

class Main
{
     constructor()
     {
         requestAnimationFrame(this.update);  //fine    
     }

     update(): void
     {
         requestAnimationFrame(this.update);  //error, because this is window
     }

}
Run Code Online (Sandbox Code Playgroud)

似乎我需要一个代理,所以让我们说使用Jquery

class Main
{
     constructor()
     {
         this.updateProxy = $.proxy(this.update, this);
         requestAnimationFrame(this.updateProxy);  //fine    
     }

     updateProxy: () => void
     update(): void
     {
         requestAnimationFrame(this.updateProxy);  //fine
     }

}
Run Code Online (Sandbox Code Playgroud)

但是来自Actionscript 3的背景,我不确定这里发生了什么.抱歉,我不确定Javascript的开始位置和TypeScript结束.

updateProxy: () => void
Run Code Online (Sandbox Code Playgroud)

而且,我不相信我这样做是对的.我想要的最后一件事是我的班级大部分都有aa()函数需要访问,aProxy()因为我觉得我写两次相同的东西?这是正常的吗?

bas*_*rat 105

如果你想要this捕获TypeScript的方法是通过箭头函数.引用安德斯:

this沿箭头功能的词法作用域

以下是我喜欢使用此方法的方法:

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;      
}
Run Code Online (Sandbox Code Playgroud)

在TypeScript Playground中查看此内容

您可以看到在生成的JavaScript this中,在函数调用之外捕获:

var _this = this;
this.prop = 10;
this.func1 = function (arg) {
    return arg + " yeah" + _this.prop;
};
Run Code Online (Sandbox Code Playgroud)

所以this函数调用中的值(可能是window)将不会被使用.

要了解更多信息:" this在TypeScript中理解"(4:05) - YouTube

  • 你必须观看视频 - 非常有用.仅需5分钟 (16认同)
  • 这不是必需的.您所建议的是惯用的JavaScript,但TypeScript使这不必要. (2认同)

joe*_*net 17

如果你写这样的方法,'this'将按你期望的方式对待.

class Main
{
    constructor()
    {
        requestAnimationFrame(() => this.update());
    }

    update(): void
    {
        requestAnimationFrame(() => this.update());
    }
}
Run Code Online (Sandbox Code Playgroud)

另一种选择是将'this'绑定到函数调用:

class Main
{
    constructor()
    {
        requestAnimationFrame(this.update.bind(this));
    }

    update(): void
    {
        requestAnimationFrame(this.update.bind(this));
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 根据我的经验,更新函数更好地定义如下:update =()=> {...} (2认同)

Kar*_*chi 9

聚会已经很晚了,但我认为对于这个问题的未来访问者来说,考虑以下几点非常重要:

其他答案,包括已接受的答案,都忽略了一个关键点:

myFunction() { ... }
Run Code Online (Sandbox Code Playgroud)

myFunction = () => { ... }
Run Code Online (Sandbox Code Playgroud)

不是同一件事“除了后者捕获的例外this”。

第一个语法在原型上创建一个方法,而第二个语法在值为函数的对象上创建一个属性(也恰好捕获this)。您可以在转译的 JavaScript 中清楚地看到这一点。

完整:

myFunction = function() { ... }
Run Code Online (Sandbox Code Playgroud)

与第二种语法相同,但没有捕获。

因此,在大多数情况下使用箭头语法可以解决绑定到对象的问题,但它并不相同,并且在很多情况下您确实希望在原型上使用适当的函数而不是属性。

在这些情况下,使用代理.bind()实际上正确的解决方案。(尽管可读性受到影响。)

更多阅读内容请参见此处(主要不是关于 TypeScript,但原则是成立的):

https://medium.com/@charpeni/arrow-functions-in-class-properties-might-not-be-as-great-as-we-think-3b3551c440b1

https://ponyfoo.com/articles/binding-methods-to-class-instance-objects


Sim*_*ver 5

参见打字稿语言规范的第72页 https://github.com/Microsoft/TypeScript/blob/master/doc/TypeScript%20Language%20Specification.pdf?raw=true

箭头函数表达式

在这个例子中

class Messenger {
 message = "Hello World";
 start() {
 setTimeout(() => alert(this.message), 3000);
 }
};
var messenger = new Messenger();
messenger.start();
Run Code Online (Sandbox Code Playgroud)

使用箭头函数表达式会使回调与周围的“开始”方法具有相同的含义。将回调写为标准函数表达式,必须手动安排对其周围环境的访问,例如,将其复制到局部变量中:

这是实际生成的Javascript:

class Messenger {
 message = "Hello World";
 start() {
 var _this = this;
 setTimeout(function() { alert(_this.message); }, 3000);
 }
};
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,链接已损坏 (2认同)

Pet*_*ris 5

当您将函数作为回调传递时,就会出现问题。当回调执行时,“this”的值可能已更改为窗口、调用回调的控件或其他内容。

确保在传递对要回调的函数的引用时始终使用 lambda 表达式。例如

public addFile(file) {
  this.files.push(file);
}
//Not like this
someObject.doSomething(addFile);
//but instead, like this
someObject.doSomething( (file) => addFile(file) );
Run Code Online (Sandbox Code Playgroud)

这编译成类似的东西

this.addFile(file) {
  this.files.push(file);
}
var _this = this;
someObject.doSomething(_this.addFile);
Run Code Online (Sandbox Code Playgroud)

因为 addFile 函数是在特定对象引用 (_this) 上调用的,所以它不使用调用者的“this”,而是使用 _this 的值。