Javascript 根据回调的构造方式,回调也可以定义为闭包吗?

Javascript 根据回调的构造方式,回调也可以定义为闭包吗?,javascript,closures,callback,Javascript,Closures,Callback,在JavaScript中,我知道闭包可以定义为一个嵌套函数,可以访问其包含函数的变量。例如: function outerFunction(x, y) { function innerFunction() { return x + y + 10; } return innerFunction; } 现在,下面的代码正在为request对象的onreadystatechange属性连接回调;然而,我想知道,根据定义,这是否也被认为是一种结束: /* Thi

在JavaScript中,我知道闭包可以定义为一个嵌套函数,可以访问其包含函数的变量。例如:

function outerFunction(x, y) {
    function innerFunction() {
        return x + y + 10;
    }
    return innerFunction;
}
现在,下面的代码正在为request对象的
onreadystatechange
属性连接回调;然而,我想知道,根据定义,这是否也被认为是一种结束

/* This is a contrived example, I know. 
 * Bear with me - it demonstrates the point I'm trying to convey. */

function submitHandler() {

    var oRequest = createRequest(); // assume I'm getting an instance of the xhr
    var sUsername = 'Tom';          // assume this is needed for work in the handler
    var This = this;
    oRequest.onreadystatechange = function() {
        This.handleResponse(oRequest, sUsername)
    }

}

function handleResponse(oResponse, sUsername) {
    if(oResponse.readyState === 4 && oResponse.status === 200) {
        // do work with the username
    } else {
        // we're not done yet...
    }
}

我意识到
handleResponse
函数也可以在
submitHandler
的上下文中作为匿名函数编写,但是我发现,如果回调被定义在回调函数的范围之外,那么更复杂的Ajax代码更容易阅读和维护。同样,这是一个人为的例子,我希望用它来简单地说明我问题的要点。

是的,你假设它是一个定义上的闭包是正确的


听起来你好像知道你的东西,但我完全同意过多的内联闭包函数并不能提高可读性。另一方面,我非常不喜欢编写闭包的
var self=this
风格,
this
只是它的一个变体,因为它的声明仍然过于冗长,并且您引入了自己的新“关键字”,无论是
this
还是
self

您需要的是对该方法进行curry/bind

function $A(o)
{
    var a = [];
    for (var i = 0; i < o.length; ++i)
        a.push(o[i]);
    return a;
}

Function.prototype.bind = function()
{
   var _method = this;
   var a = $A(arguments)
   var o = a.shift();

   return function()
   {
       return _method.apply(o, a.concat($A(arguments)));
   }
}

Function.prototype.curry = function()
{
   var _method = this;
   var a = $A(arguments);

   return function()
   {
       return _method.apply(null, a.concat($A(arguments)));
   }
}
你现在可以写:

oRequest.onreadystatechange = this.handleResponse.curry(oRequest,sUsername);
然而,若你们想传递这个关键字的意思,你们可以这样做

oRequest.onreadystatechange = this.handleResponse.bind(this,oRequest,sUsername);

handleResponse
调用时,将具有与
提交者相同的
上下文。如果您返回了innerFunction,那么它将是正确的,但是您正在执行innerFunction并返回结果

第二个示例可以使用闭包。这种特定技术的一个警告是,在某些浏览器实现中(当然也可能是其他的)可能会导致相当严重的内存泄漏。您将在oRequest中保存的xhr、引用函数的onreadystatechange和保存xhr的函数范围之间创建一个循环引用。xhr不仅会保留在内存中,而且响应也会保留在内存中,如果响应很大(尤其是XML),它会快速占用内存


在处理响应期间,将onreadystatechange属性设置为空的全局级别函数。这将打破这个循环。

感谢大家的提醒-编辑了我最初的闭包示例。另外,我喜欢你们关于oRequest的循环引用的讨论。我通常不会这样编写生产级代码,但这似乎是解决这个问题的一个快速示例。
oRequest.onreadystatechange = this.handleResponse.bind(this,oRequest,sUsername);