JavaScript对象事件处理程序作用域,最佳实践是什么?

3

我正在编写一个Javascript模块,主要提供一个提交表单的功能。

在编写过程中,我遇到了一个看起来很典型的作用域问题。

我希望submit()方法能够进行AJAX调用,并使用对象方法来处理调用的成功和失败。由于submit()是一个事件处理程序,因此this不再设置为flagBox对象。因此,我无法再访问flagBox.showSuccess()flagBox.showFail()

起初,我正在寻找一种设置对象范围内自身引用的方式,以便我可以调用类似self.showSuccess()的方法。

目前,我正在使用jQuery.proxy()来设置处理程序的上下文。

我还考虑实现发布/订阅模式或将该方法附加到event.data上。

我很好奇是否存在其他解决方案,以及是否有任何我尚未发现的“最佳实践”。

(function( $ ) {

    var FlagBox = function() {};
    FlagBox.prototype = {

        constructor: FlagBox,

        init: function() {
            $('.flag-content-box')
                .on('submit', $.proxy(this.submit, this));
        },

        ...

        showSuccess: function() {
            console.log('success');
        },

        showFail: function() {
            console.log('fail');
        },

        submit: function(event) {
            event.preventDefault();

            var that = this;
                formData = $(event.target).serializeObject();

            $.ajax({
                type:"POST",
                url: '/flag/add.json',
                data: formData,
                success : function(data) {
                    that.showSuccess();
                },
                error : function(jqXHR, textStatus, errorThrown) {
                    showFail();
                }
            });
        }
    };

    var flagBox = new FlagBox();
    flagBox.init();

})(jQuery);

使用 var that = this; 是一种常见(我认为也是适当的)模式。 - go-oleg
1个回答

0
您可以像下面这样将成功/失败方法绑定到您的对象。这样,总是会使用您的对象上下文调用成功/失败方法。
(function( $ ) {

    var FlagBox = function() {};
    FlagBox.prototype = {

        constructor: FlagBox,

        init: function() {
            $('.flag-content-box')
                .on('submit', $.proxy(this.submit, this));
        },

        ...

        showSuccess: function() {
            console.log('success');
        },

        showFail: function() {
            console.log('fail');
        },

        submit: function(event) {
            event.preventDefault();

            var that = this;
                formData = $(event.target).serializeObject();

            var successFn = (function(obj){
                return function(){
                    return obj.showSuccess.apply(obj, arguments)
                }
            })(this);  

            var failureFn = (function(obj){
                return function(){
                    return obj.showFailure.apply(obj, arguments);
                }
            })(this);  

            $.ajax({
                type:"POST",
                url: '/flag/add.json',
                data: formData,
                success : successFn,
                error : failureFn
            });
        }
    };

    var flagBox = new FlagBox();
    flagBox.init();

})(jQuery);

使用 bind 似乎更简单:var successFn = this.showSuccess.bind(this); - go-oleg
bind 函数是 JS 的最新版本,第五版的新增功能,可能不会在所有浏览器中出现。 - mohkhan
这里传递给successFn()this不是对象的上下文,而是事件处理程序的上下文,你是不是想传递that - Will M
无论事件处理程序将什么传递给successFn,它最终都会使用该对象调用成功/失败方法。 - mohkhan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接