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