Jquery Typescript";这";类方法内部

Jquery Typescript";这";类方法内部,jquery,this,typescript,proxy-classes,Jquery,This,Typescript,Proxy Classes,我知道这可能是痛苦的基础,但我有一个艰难的时候,我的头围绕着它 class Main { constructor() { requestAnimationFrame(this.update); //fine } update(): void { requestAnimationFrame(this.update); //error, because this is window } }

我知道这可能是痛苦的基础,但我有一个艰难的时候,我的头围绕着它

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

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

}
看起来我需要一个代理,所以让我们假设使用Jquery

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

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

}
但是来自ActionScript3的背景,我不确定这里发生了什么。抱歉,我不确定Javascript从哪里开始,TypeScript从哪里结束

updateProxy: () => void

而且,我不相信我做得对。我最不想看到的是,我的大多数类都有一个a()函数,需要使用
aProxy()
来访问它,因为我觉得我在两次编写相同的东西?这正常吗?

简而言之,this关键字总是引用调用函数的对象

在Javascript中,因为函数只是变量,所以可以传递它们

例如:

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
使用jQuery执行以下操作时:

$.proxy(this.update, 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
  }
};

如果您想捕获此,则可以通过箭头函数来捕获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;      
}

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

var _this = this;
this.prop = 10;
this.func1 = function (arg) {
    return arg + " yeah" + _this.prop;
};
class Main
{
    constructor()
    {
        requestAnimationFrame(this.update.bind(this));
    }

    update(): void
    {
        requestAnimationFrame(this.update.bind(this));
    }
}
因此,函数调用中的
这个
值(可能是
窗口
)将不会被使用


要了解更多信息:

如果您这样编写方法,“this”将按您期望的方式处理

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

    update(): void
    {
        requestAnimationFrame(() => this.update());
    }
}
另一个选项是将“this”绑定到函数调用:

var _this = this;
this.prop = 10;
this.func1 = function (arg) {
    return arg + " yeah" + _this.prop;
};
class Main
{
    constructor()
    {
        requestAnimationFrame(this.update.bind(this));
    }

    update(): void
    {
        requestAnimationFrame(this.update.bind(this));
    }
}

参见typescript语言规范第72页

箭头函数表达式 在这个例子中

class Messenger {
 message = "Hello World";
 start() {
 setTimeout(() => alert(this.message), 3000);
 }
};
var messenger = new Messenger();
messenger.start();
使用arrow函数表达式会导致回调具有 这与周围的“开始”方法相同。编写回调 作为标准函数表达式,需要手动 安排对此周围环境的访问,例如将其复制到 局部变量:

这是实际生成的Javascript:

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

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

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

public addFile(file) {
  this.files.push(file);
}
//Not like this
someObject.doSomething(addFile);
//but instead, like this
someObject.doSomething( (file) => addFile(file) );
这编译成类似于

this.addFile(file) {
  this.files.push(file);
}
var _this = this;
someObject.doSomething(_this.addFile);

因为在特定对象引用上调用AdfFrm函数(这是),它不使用调用方的“这个”,而是这个“./P>>P>的值”到了晚会的很晚,但是我认为对于这个问题的未来访问者来说,考虑下面的内容非常重要:

其他答案,包括公认的答案,忽略了一个关键点:

myFunction(){…}

myFunction=()=>{…}
不是同一件事,只是后者捕获了
这个

第一种语法在原型上创建一个方法,而第二种语法在对象上创建一个属性,该对象的值是一个函数(捕捉
this
)。您可以在传输的JavaScript中清楚地看到这一点

待完成:

myFunction=function(){…}
与第二种语法相同,但没有捕获

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

在这些情况下,使用代理或
.bind()
实际上是正确的解决方案。(尽管可读性较差。)

更多阅读(主要不是关于打字脚本,而是原则):


这样做怎么样? 声明类型为“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();

注意:重要的是不要使用“self”,因为它已经是一个特殊的含义。

这是不必要的。您所建议的是惯用JavaScript,但TypeScript使这一点变得不必要。@在TS 0.9.1之前,不允许在类成员的上下文中使用箭头函数(这个答案是在此之前的)。新语法的更新答案:)你必须观看视频-非常有用。只有5分钟谢谢你,@basarat。当我看到您在视频播放到一半的时候使用了箭头功能时,灯泡就亮了起来。非常感谢。@AaronLS在TypeScript操场上生成
var\u this=this您必须选择
ES5
;自ES2015-内部函数-
这个
被用来代替
\u这个
在我的经验中,更新函数的定义是这样的:update=()=>{…}我一直在使用typescript很多次,并且已经来回更改了很多次。目前,如果它不仅仅是一个简单的方法调用,我只包含花括号。另外,当使用typescript+linq(这是神圣的)时,格式会更好。示例:可枚举的.From(arr).Where(o=>o.id==123);我想如果你看看生成的javascript,你会发现一个显著的不同。这不是品味的问题。update=()=>{}将通过“var\u this=this”编译创建词法作用域,但您的语法不会。您可能需要升级您的TypeScript库,因为它绝对包含“\u this”上下文。使用“()=>code()”或()=>{return code();}”将输出100%相同的javascript代码。以下是输出:。您还可以通过将代码粘贴到绑定中来亲自查看(这可能是不好的,因为它在原始函数args上失去了类型安全性。当您说出编译的内容时,您将显示哪一个?(arrow实例还是刚刚通过method对象的实例?)lambda。只需使用该代码创建一个TS,然后看看它是什么