You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XMLHttpRequest对象何时会被回收?

XMLHttpRequest 对象的垃圾回收疑问解答

先看你提供的代码和场景:

<script>
function ajax_async(method, url, body, cb) {
 var r = new XMLHttpRequest();
 r.open(method, url, true);
 r.onreadystatechange = cb;
 r.send(body);
}
ajax_async('GET', '/sleep.php', null, function() {
 if(this.readyState==4) alert('123');
});
</script>

补充场景:sleep.php 仅会休眠10秒后返回结果。

下面针对你的问题逐一解释:

为什么局部变量 r 对应的XHR对象在请求运行时没被回收?

没错,r 是 ajax_async 函数的局部变量,函数执行结束后外部确实无法直接访问它,但有两个关键因素让这个XHR对象保持可达:

  1. 回调函数的间接引用:你给XHR对象绑定了 onreadystatechange 回调,而回调里的 this 指向该XHR对象——这意味着回调函数本身持有对XHR对象的引用,只要回调还可能被触发,这个引用就会存在。
  2. 浏览器内部的引用:在XHR请求处于活跃状态(readyState <4)时,浏览器会在内部维持对该对象的引用,确保请求能正常完成,并且能触发对应的状态变化事件。

只要对象处于可达状态(有任何引用指向它),JS的垃圾回收器就不会回收它。

当 readyState==4 后,该对象会被回收吗?

满足条件的话会被回收,但不是立刻。当 readyState 变为4(请求完成):

  • 首先浏览器会释放它内部对该XHR对象的引用;
  • 其次,你的回调函数执行完毕后,如果没有其他代码再持有对这个XHR对象的引用(比如没把它赋值给全局变量、闭包变量或者持久DOM元素的属性),那么这个XHR对象就会变成不可达状态。

此时,垃圾回收器在下一次运行时(比如引擎空闲阶段)就会标记这个对象为垃圾并回收它。

如果不会,它何时会被回收?

只有当所有指向该XHR对象的引用都被清除时,它才会被回收:

  • 如果你在回调里把XHR对象保存到了某个持久化的地方(比如 window.xhr = this),那它会一直存在,直到你手动清除这个引用(比如 window.xhr = null);
  • 如果没有额外的引用,那么在浏览器内部引用释放、回调执行完成且没有闭包残留引用后,垃圾回收器会按照自身的策略(比如标记清除、分代回收)在合适的时机回收它。

是否有相关规范明确说明 readyState==4 表示“可回收”,而其他状态则不可?

规范不会直接用“可回收”这种表述,但从XMLHttpRequest的官方规范设计逻辑可以推导出来:

  • 当XHR处于未完成状态(readyState <4)时,规范要求浏览器必须维持对象的生命周期,保证请求能按阶段触发状态变化事件,因此浏览器会持有引用,对象处于可达状态;
  • 当readyState变为4后,请求的所有生命周期事件都已触发完成,规范不再要求浏览器维持该对象的引用,此时只要用户代码中没有保留引用,对象就会进入可回收的不可达状态。

垃圾回收的核心规则始终是对象的可达性,规范只是定义了XHR对象的生命周期边界,间接影响了它的回收时机。

内容的提问来源于stack exchange,提问作者firk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 05:37:27