在TypeScript中确定'this'的范围

时间:2013-05-03 14:21:26

标签: javascript typescript

我有一个非常简单的类,但在Typescript中定义'this'已经遇到了痛苦:

打字稿

/// <reference path='jquery.d.ts' />
/// <reference path='bootstrap.d.ts' />

module Problem {
    export class Index {
        detailsUrl: string;
        constructor() {
            $('.problem-detail-button').click((e) => {

                e.preventDefault();

                var $row = $(this).closest('tr'); //this must be that of the callback
                var problemId: number = $row.data('problem-id');

                $.ajax({
                    url: this.detailsUrl, //this must be the instance of the class
                    data: { id: problemId },
                    type: 'POST',
                    success: (result) => {
                        $('#details-modal-placeholder').html(result);
                        $('#details-modal-placeholder modal').modal('show');
                    },
                })
            });
        }
    }
}

的Javascript

var Problem;
(function (Problem) {
    var Index = (function () {
        function Index() {
            var _this = this;
            $('.problem-detail-button').click(function (e) {
                e.preventDefault();
                var $row = $(_this).closest('tr');
                var problemId = $row.data('problem-id');
                $.ajax({
                    url: _this.detailsUrl,
                    data: {
                        id: problemId
                    },
                    type: 'POST',
                    success: function (result) {
                        $('#details-modal-placeholder').html(result);
                        $('#details-modal-placeholder modal').modal('show');
                    }
                });
            });
        }
        return Index;
    })();
    Problem.Index = Index;    
})(Problem || (Problem = {}));

现在的问题是该行

var $row = $(this).closest('tr'); //this must be that of the callback

和这一行

this.detailsUrl, //this must be the instance of the class

'this'意思冲突

你如何处理'this'的混合?

6 个答案:

答案 0 :(得分:12)

module Problem {
export class Index {
    detailsUrl: string;
    constructor() {
        var that = this;
        $('.problem-detail-button').click(function (e) {
            e.preventDefault();
            var $row = $(this).closest('tr'); //this must be that of the callback
            var problemId: number = $row.data('problem-id');

            $.ajax({
                url: that.detailsUrl, //this must be the instance of the class
                data: { id: problemId },
                type: 'POST',
                success: (result) => {
                    $('#details-modal-placeholder').html(result);
                    $('#details-modal-placeholder modal').modal('show');
                },
            })
        });
    }
}
}

明确声明that = this,以便您有that.detailsUrl的引用,然后 不要使用胖箭头作为点击处理程序,因此您可以获得正确的this回调范围。

Playground

答案 1 :(得分:8)

您需要回退到javascript的标准方式。即将变量存储为:

var self = this; 

然后,您可以使用function代替()=>,并使用this访问回调中的变量,self访问该类的实例。

以下是完整的代码示例:

module Problem {
    export class Index {
        detailsUrl: string;
        constructor() {
            var self = this; 
            $('.problem-detail-button').click(function(e){

                e.preventDefault();

                var $row = $(this).closest('tr'); //this must be that of the callback
                var problemId: number = $row.data('problem-id');

                $.ajax({
                    url: self.detailsUrl, //this must be the instance of the class
                    data: { id: problemId },
                    type: 'POST',
                    success: (result) => {
                        $('#details-modal-placeholder').html(result);
                        $('#details-modal-placeholder modal').modal('show');
                    },
                })
            });
        }
    }
}

// Creating 
var foo:any = {};
foo.x = 3;
foo.y='123';

var jsonString = JSON.stringify(foo);
alert(jsonString);


// Reading
interface Bar{
    x:number;
    y?:string; 
}

var baz:Bar = JSON.parse(jsonString);
alert(baz.y);

您生成的javascript:

var Problem;
(function (Problem) {
    var Index = (function () {
        function Index() {
            var self = this;
            $('.problem-detail-button').click(function (e) {
                e.preventDefault();
                var $row = $(this).closest('tr');
                var problemId = $row.data('problem-id');
                $.ajax({
                    url: self.detailsUrl,
                    data: {
                        id: problemId
                    },
                    type: 'POST',
                    success: function (result) {
                        $('#details-modal-placeholder').html(result);
                        $('#details-modal-placeholder modal').modal('show');
                    }
                });
            });
        }
        return Index;
    })();
    Problem.Index = Index;    
})(Problem || (Problem = {}));
var foo = {
};
foo.x = 3;
foo.y = '123';
var jsonString = JSON.stringify(foo);
alert(jsonString);
var baz = JSON.parse(jsonString);
alert(baz.y);

答案 2 :(得分:2)

如果您只支持拥有.addEventListener的浏览器,我建议您使用它来将您的数据与您的元素相关联。

我只是举一个简单的例子,而不是实现你的代码。

function MyClass(el) {
    this.el = el;
    this.foo = "bar";
    el.addEventListener("click", this, false);
}

MyClass.prototype.handleEvent = function(event) {
    this[event.type] && this[event.type](event);
};

MyClass.prototype.click = function(event) {
    // Here you have access to the data object
    console.log(this.foo); // "bar"

    // ...and therefore the element that you stored
    console.log(this.el.nodeName); // "DIV"

    // ...or you could use `event.currentElement` to get the bound element
};

因此,这种技术为您提供了元素和数据之间的有组织耦合。

即使你需要支持旧的IE,也可以使用.attachEvent()来填充它。

然后使用它,您只需在设置数据时将元素传递给构造函数。

new MyClass(document.body);

如果所有逻辑都在你的处理程序中,你甚至不需要保留对你创建的对象的引用,因为处理程序会自动通过this获取它。

答案 3 :(得分:1)

我通常会在我想要的范围内将this绑定到变量。

然而你所追随的this可以这样找到:

constructor() {
    var class_this=this;
    $('.problem-detail-button').click(function (e) {
        e.preventDefault();
        var callback_this=e.target;

答案 4 :(得分:0)

线程的后期,但我的建议有所不同。

而不是:

var $row = $(this).closest('tr'); //this must be that of the callback

考虑使用:

var $row = $(e.currentTarget).closest('tr');

在此示例中,您可能希望在jQuery回调中使用this的任何位置,您可以访问可以使用的函数参数。我建议使用这些参数代替this更清晰(其中“清洁”被定义为更具表现力,并且在将来维护期间不太可能变成错误)。

答案 5 :(得分:0)

module Problem {
export class Index {
    constructor() {
        $('.classname').on('click',$.proxy(this.yourfunction,this));
    }
    private yourfunction(event){
        console.log(this);//now this is not dom element but Index
    }
}
}

检查jquery.proxy()。 只是提醒你还有另一种方式。