使用AJAX澄清Javascript中的闭包

使用AJAX澄清Javascript中的闭包,javascript,ajax,closures,Javascript,Ajax,Closures,我应该已经理解了Javascript中的Cloures,但我显然没有 目前,我正在阅读的文本具有以下功能来抽象AJAX调用: function request(url, callback){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = (function(myxhr){ return function(){ callback(myxhr); } })(xhr); xhr.open('

我应该已经理解了Javascript中的Cloures,但我显然没有

目前,我正在阅读的文本具有以下功能来抽象AJAX调用:

function request(url, callback){
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = (function(myxhr){
    return function(){
      callback(myxhr);
    }
  })(xhr);
  xhr.open('GET', url, true);
  xhr.send('');
}
这是我的实际问题:我的大脑拒绝理解为什么这个不能工作:

function request(url, callback){
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = callback(xhr);
  xhr.open('GET', url, true);
  xhr.send('');
}
function request(url, callback){
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = callback(xhr);
  xhr.open('GET', url, true);
  xhr.send('');
}
我的意思是,以“我”的方式,我想象会发生的是,我称之为“说请求”http://...,一个_回调)。在request()中,将创建一个新的xhr对象,并将其分配给回调函数。。。这不管用吗?(令人讨厌的)副作用是什么?根据我(有限的)理解,例如在一个循环中,您可能最终引用函数变量的最新值时,需要闭包。但是在这里。。。“var xhr=…”不是确保每次都创建一个新对象吗


请解释一下,好像我的智商是30(这可能是真的:D)


Merc.

当您编写
xhr.onreadystatechange=callback(xhr)
时,您立即调用
callback
,并将其结果分配给
onreadystatechange
,在代码中显示您实际上调用
callback
,因为
()
结尾。

在第一个示例中,您不需要额外的闭包。这很好:

function request(url, callback){
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function(){
      callback(xhr);
  };
  xhr.open('GET', url, true);
  xhr.send('');
}
在现代浏览器中,您还可以执行以下操作:

function request(url, callback){
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = callback.bind(null, xhr);
  xhr.open('GET', url, true);
  xhr.send('');
}
编辑-还要注意提供的答案@Raynos。您实际上不需要将XHR对象作为参数传递

再次编辑-回应一条合法的评论,你问为什么你原来的想法行不通:

function request(url, callback){
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = callback(xhr);
  xhr.open('GET', url, true);
  xhr.send('');
}
function request(url, callback){
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = callback(xhr);
  xhr.open('GET', url, true);
  xhr.send('');
}
这里的线路有问题:

  xhr.onreadystatechange = callback(xhr);

将调用回调函数返回的值分配给
onreadystatechange
。换句话说,当状态改变时,不建立要调用的东西,而是立即进行调用。这种错误很常见,因为很容易读错。但是,JavaScript在任何时候都会看到一个函数引用后面跟着一个括号内的参数列表,该列表被解释为执行函数调用的请求,而不是对未来函数调用的函数包装的请求。

问得好。函数调用和指向函数的指针之间有一个重要的区别——你想给它们一个指向函数的指针(不是真的,它是一个闭包,但这就是我所调用的),这样它们以后就可以调用它了。如果您曾经进行函数式编程,或者使用Lisp系列中的任何东西,这一点非常重要。

您不需要将
xhr
传递给回调函数

您只需执行
xhr.onreadystatechange=callback

然后使用
this
引用回调中的
xhr
对象

示例:

xhr.onreadystatechange = function () {
  console.log(this.readystate);
};

免责声明:对于C和大多数其他通用语言中的跨浏览器支持的某些价值,函数返回后,所有局部变量都不再可访问,因为堆栈框架已被破坏


在JavaScript中,如果您在另一个函数中声明一个函数,那么从您调用的函数返回后,局部变量仍然可以访问。

我回答我自己的问题,因为编辑会混淆一切——如果不是这样做的话,请原谅

所以。。。在我的例子中,我实际上想写的是:

function request(url, callback){
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function(){ callback(xhr); }
  xhr.open('GET', url, true);
  xhr.send('');
}
或者,因为我不需要xhr(我可以使用“this”):

所以,最后,我是对的。。。使用闭包(如原问题所示)完全是浪费时间,对吗

如果有一个循环,这将是很重要的,我必须设置几个回调。但是在这种情况下,由于每次调用“request”时都会创建一个新的xhr,并且它是用正确的回调设置的,因此实际上不需要闭包。。对吧?


美塞苔丝。

请解释一下,就好像我的智商是30一样-你的问题听起来更像是“阿贾克斯,你不工作,请帮忙,紧急!!!!!1111”。-)嗯,我甚至在写问题的时候把“我的”例子弄错了,所以我想我用英语写作会获得额外的分数,但仅此而已!嗯<代码>此
?哦,对,;因为浏览器使用XHR对象作为接收器调用XHR回调。(对吗?)因为这就是工作原理。见4.6。XHR是一个事件目标,
目标
是XHR对象。所以我可以写这个,对吗?函数请求(url,回调){var xhr=new-XMLHttpRequest();xhr.onreadystatechange=callback;xhr.open('GET',url,true);xhr.send('';}是的,您也可以这样做!唯一的问题是浏览器不会将XHR对象作为参数传递,但它会为您将其设置为
this
值。。。结果证明我是对的!顺便说一句,我得到了Stoyan Stefanov的“面向对象Javascript”的闭包示例。一本很棒的书,但是258页的例子,以xhr为结尾,真的让我很惊讶。。。我想“好吧,我不会在这里用闭包,他用了,所以我会塞住……但为什么要闭包?!”。我用头撞了它大约两个小时,试图弄明白为什么你可能需要关闭它。。。事实证明你没有投票,因为这并不能解释为什么在他的例子中它不起作用。