TypeScript中是否有"this"的别名? [英] Is there an alias for 'this' in TypeScript?

查看:246
本文介绍了TypeScript中是否有"this"的别名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用TypeScript编写一个类,该类具有定义的方法,该方法充当jQuery事件的事件处理程序回调.

I've attempted to write a class in TypeScript that has a method defined which acts as an event handler callback to a jQuery event.

class Editor {
    textarea: JQuery;

    constructor(public id: string) {
        this.textarea = $(id);
        this.textarea.focusin(onFocusIn);
    }

    onFocusIn(e: JQueryEventObject) {
        var height = this.textarea.css('height'); // <-- This is not good.
    }
}

在onFocusIn事件处理程序中,TypeScript将"this"视为类的"this".但是,jQuery会覆盖此引用,并将其设置为与事件关联的DOM对象.

Within the onFocusIn event handler, TypeScript sees 'this' as being the 'this' of the class. However, jQuery overrides the this reference and sets it to the DOM object associated with the event.

一种选择是在构造函数中定义一个lambda作为事件处理程序,在这种情况下,TypeScript使用隐藏的_this别名创建某种闭包.

One alternative is to define a lambda within the constructor as the event handler, in which case TypeScript creates a sort of closure with a hidden _this alias.

class Editor {
    textarea: JQuery;

    constructor(public id: string) {
        this.textarea = $(id);
        this.textarea.focusin((e) => {
            var height = this.textarea.css('height'); // <-- This is good.
        });
    }
}

我的问题是,是否有另一种方法可以使用TypeScript在基于方法的事件处理程序中访问此引用,以克服这种jQuery行为?

My question is, is there another way to access the this reference within the method-based event handler using TypeScript, to overcome this jQuery behavior?

推荐答案

因此,如前所述,没有TypeScript机制可确保方法始终与它的this指针绑定(而且这不仅仅是jQuery的问题.)这并不意味着没有解决该问题的相当简单的方法.您需要为您的方法生成一个代理,该代理在调用回调之前恢复this指针.然后,您需要使用该代理包装回叫,然后再将其传递到事件中. jQuery为此有一个内置的机制,称为jQuery.proxy().这是使用该方法的上述代码的示例(请注意添加的$.proxy()调用.)

So as stated there is no TypeScript mechanism for ensuring a method is always bound to it's this pointer (and this isn't just a jQuery issue.) That doesn't mean there isn't a reasonably straightforward way to address this issue. What you need is to generate a proxy for your method that restores the this pointer before calling your callback. You then need to wrap your callback with that proxy before passing it into the event. jQuery has a built in mechanism for this called jQuery.proxy(). Here's an example of your above code using that method (notice the added $.proxy() call.)

class Editor { 
    textarea: JQuery; 

    constructor(public id: string) { 
        this.textarea = $(id); 
        this.textarea.focusin($.proxy(onFocusIn, this)); 
    } 

    onFocusIn(e: JQueryEventObject) { 
        var height = this.textarea.css('height'); // <-- This is not good. 
    } 
} 

这是一个合理的解决方案,但是我个人发现开发人员经常忘记包括代理调用,因此我想出了一个基于TypeScript的替代解决方案.使用HasCallbacks类,您需要做的就是从HasCallbacks派生您的类,然后任何以'cb_'前缀的方法将永久绑定其this指针.您根本无法使用不同的this指针来调用该方法,这在大多数情况下是更可取的.这两种机制都可以起作用,因此无论您发现哪种方法都更易于使用.

That's a reasonable solution but I've personally found that developers often forget to include the proxy call so I've come up with an alternate TypeScript based solution to this problem. Using, the HasCallbacks class below all you need do is derive your class from HasCallbacks and then any methods prefixed with 'cb_' will have their this pointer permanently bound. You simply can't call that method with a different this pointer which in most cases is preferable. Either mechanism works so its just whichever you find easier to use.

class HasCallbacks {
    constructor() {
        var _this = this, _constructor = (<any>this).constructor;
        if (!_constructor.__cb__) {
            _constructor.__cb__ = {};
            for (var m in this) {
                var fn = this[m];
                if (typeof fn === 'function' && m.indexOf('cb_') == 0) {
                    _constructor.__cb__[m] = fn;                    
                }
            }
        }
        for (var m in _constructor.__cb__) {
            (function (m, fn) {
                _this[m] = function () {
                    return fn.apply(_this, Array.prototype.slice.call(arguments));                      
                };
            })(m, _constructor.__cb__[m]);
        }
    }
}

class Foo extends HasCallbacks  {
    private label = 'test';

    constructor() {
        super();

    }

    public cb_Bar() {
        alert(this.label);
    }
}

var x = new Foo();
x.cb_Bar.call({});

这篇关于TypeScript中是否有"this"的别名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆