【问题标题】:Scope in an $.ajax callback function$.ajax 回调函数中的作用域
【发布时间】:2012-10-23 08:21:26
【问题描述】:

如果我使用此代码,为什么“doStuff”警报的范围发生了变化?有没有办法可以确保范围是我的对象而不是 Window 对象?

这是jsfiddle中的相同代码。

(function ($) {
    var c$ = {};

    c$.TestScope = function () {

        this.doAjax = function (onComplete) {
            var self = this;
            $.ajax({
                url: 'badurl',
                complete: function (data) {
                    alert('doAjax2 self === c$.oTestScope: ' + (self === c$.oTestScope).toString());
                    onComplete(data);
                }
            });
            alert('doAjax1 self === c$.oTestScope: ' + (self === c$.oTestScope).toString());  
        };

        this.doStuff = function (data) {
            var self = this;
            alert('doStuff self === c$.oTestScope: ' + (self === c$.oTestScope).toString());
        }

    };

    c$.oTestScope = new c$.TestScope();
    c$.oTestScope.doAjax(c$.oTestScope.doStuff);
})(jQuery);​

【问题讨论】:

    标签: jquery ajax callback scope


    【解决方案1】:

    我已更改您的代码,以将对 this 的引用传递给 doStuff() 代码。

    (function ($) {
        var c$ = {};
    
        c$.TestScope = function () {
    
            this.doAjax = function (onComplete) {
                var self = this;
                $.ajax({
                    url: 'badurl',
                    complete: function (data) {
                        alert('doAjax2 self === c$.oTestScope: ' + (self === c$.oTestScope).toString());
                        onComplete(data,self);
                    }
                });
                alert('doAjax1 self === c$.oTestScope: ' + (self === c$.oTestScope).toString());  
            };
    
            this.doStuff = function (data,thisRef) {
                var self = thisRef;
                alert('doStuff self === c$.oTestScope: ' + (self === c$.oTestScope).toString());
            }
    
        };
    
        c$.oTestScope = new c$.TestScope();
        c$.oTestScope.doAjax(c$.oTestScope.doStuff);
    })(jQuery);​
    

    【讨论】:

    • 那很好。我遇到的唯一问题是我总是必须将“thisRef”参数添加到“doStuff”。我通过将其添加为可选参数并在未提供该选项时将“self”设置为“this”来解决此问题。这是我更新的 jsfiddle jsfiddle.net/RW4Ge/3.
    【解决方案2】:

    您应该能够在 $.ajax() 参数中将 this 值指定为上下文:

    var c$ = {};
    
    c$.TestScope = function() {
    
        this.doAjax = function(onComplete) {
    
            alert('doAjax1 this === c$.oTestScope: ' + (this === c$.oTestScope).toString());
    
            $.ajax({
                url: 'badurl',
                context: this,
                complete: function(data) {
                    alert('doAjax2 this === c$.oTestScope: ' + (this === c$.oTestScope).toString());
                    onComplete.call(this, data);
                }
            });
        };
    
        this.doStuff = function(data) {
            alert('doStuff this === c$.oTestScope: ' + (this === c$.oTestScope).toString());
        }
    
    };
    
    c$.oTestScope = new c$.TestScope();
    c$.oTestScope.doAjax(c$.oTestScope.doStuff);
    

    编辑我为此创建了一个fiddle 并验证它可以正常工作。无需使用额外的 self 参数,也无需使用闭包来保留变量。

    您缺少的部分内容是调​​用onComplete.call(this, data) 来调用doStuff()

    【讨论】:

    • 上下文选项似乎只在您直接调用函数“context:onComplete”时才起作用。我看不出有任何方法可以使用此方法获得默认功能和回调功能。这是带有上下文选项jsfiddle.net/RW4Ge/2的jsfiddle。
    • 我知道你已经选择了你的解决方案,但请看看这个版本。它干净利落地解决了this 的问题,而无需使用任何额外的闭包或临时变量。
    • 感谢您的帮助,也许我遗漏了一些东西,但您的示例未使用 onComplete 回调。它直接调用doStuff。如果将 this.doStuff(data) 更改为 onComplete(data)(this === c$.oTestScope) 将返回 false。我同意你的语法更干净。如果我可以让它工作,我会使用它。
    • 如果需要使用传入的函数,那么你要使用onComplete.call(this, data);this.doStuff()一样,只不过传入的函数无论如何都可以使用是。
    • 完美。这样做。谢谢你一直陪着我。
    猜你喜欢
    • 1970-01-01
    • 2011-03-10
    • 1970-01-01
    • 1970-01-01
    • 2021-02-01
    • 1970-01-01
    • 2017-03-31
    • 1970-01-01
    • 2014-07-08
    相关资源
    最近更新 更多