如何重构这个Javascript匿名函数?

时间:2010-03-30 00:48:31

标签: javascript jquery

我们的代码中有这个匿名函数,它是jQuery的Ajax对象参数的一部分,它使用调用它的函数中的一些变量。

this.invoke = function(method, data, callback, error, bare) {
      $.ajax({
        success: function(res) {
            if (!callback) return;

            var result = "";
            if (res != null && res.length != 0)
                var result = JSON2.parse(res);

            if (bare)
            { callback(result); return; }

            for (var property in result) {
                callback(result[property]);
                break;
            }
        }
   });
}

我省略了额外的代码,但你明白了。代码工作得很好,但它在IE中每次调用时泄漏4 Kbs,所以我想重构它以将匿名函数转换为命名函数,如this.onSuccess = function(res){..}。

问题是这个函数使用了this.invoke(..)中的变量,所以我不能把它带到它的体外。如何正确重构此代码,以便使用匿名函数和父函数变量?

更新。我正在考虑创建一个单独的对象,使用相同的参数初始化它,并将其onSuccess函数作为jQuery的Ajax对象的参数传递。虽然我怀疑它仍会泄漏内存。

更新2。我发现一些链接表明实际的泄漏可能是由jQuery引起的。 Simple jQuery Ajax call leaks memory in Internet Explorer Memory leak involving jQuery Ajax requests

找到一种重构方法仍然很好。

更新3。我会在接受答案之前等待更通用的解决方案。

2 个答案:

答案 0 :(得分:10)

您可以在成功回调中访问的ajax请求中添加额外的参数:

this.invoke = function(method, data, callback, error, bare) {
    $.ajax({
        success: onSuccess,
        invokedata: {
         callback: callback,
         bare: bare
        }
    });
};

var onSuccess = function(res) {
    var callback = this.invokedata.callback,
        bare = this.invokedata.bare;
    if (!callback) return;

    var result = "";
    if (res != null && res.length != 0)
        var result = JSON2.parse(res);

    if (bare){
        callback(result); 
        return;
    }

    for (var property in result) {
        callback(result[property]);
        break;
    }
}

答案 1 :(得分:4)

+1为优秀,优秀的问题 - 我感觉到你的痛苦 - 这是非常好的因素。

一个建议(也许这就是你更新的意思)...为onSuccess定义一个包装器并让它返回你想要分配的函数。然后调用外部函数并将其分配给“success”选项,传递它需要的值。这些值将预先分配给内部函数中的变量。实际上并不确定这是否会有所帮助 - 你仍然会得到一个匿名函数 - 但值得一试

this.invoke = function(method, data, callback, error, bare) {
    $.ajax({
        success: onSuccess(callback, bare);
    });
};

var onSuccess = function(callback, bare) {
     return function() {
        if (!callback) return;

        var result = "";
        if (res != null && res.length != 0)
            var result = JSON2.parse(res);

        if (bare)
        { callback(result); return; }

        for (var property in result) {
            callback(result[property]);
            break;
        }
     }
}