对象方法内使用setTimeout导致代码无法终止的问题
为啥你的setTimeout递归停不下来?
先把你的代码贴出来方便咱们分析:
var myObj = { myFunc: function () { var self = this; var timer = setTimeout(function () { console.log('Timeout called'); self.myFunc(); }, 100); } }; myObj.myFunc(); myObj = null;
核心问题:闭包攥着原对象的引用没放
你以为把myObj = null就能让对象被垃圾回收,但实际上**self变量在setTimeout的回调闭包里,还死死引用着最初的myObj对象**。当你第一次调用myObj.myFunc()时,this指向的是原对象,self把这个引用存了下来——哪怕外部的myObj变量被设为null,闭包里的self还抓着原对象不放,所以它不会被销毁,self.myFunc()会一直递归调用,定时器自然停不下来。
两种实用修复方案
你需要主动给递归加个“刹车”,这里给你两种常用的思路:
方案1:加个停止标志
给对象加一个状态变量,每次调用myFunc前先检查这个标志:
var myObj = { isStopped: false, myFunc: function () { if (this.isStopped) return; // 触发停止就直接返回 var self = this; var timer = setTimeout(function () { console.log('Timeout called'); self.myFunc(); }, 100); } }; myObj.myFunc(); // 比如500毫秒后停止 setTimeout(() => { myObj.isStopped = true; }, 500);
方案2:保存定时器ID,手动清除
把定时器ID存在对象里,专门写个方法来清除定时器:
var myObj = { timerId: null, myFunc: function () { var self = this; this.timerId = setTimeout(function () { console.log('Timeout called'); self.myFunc(); }, 100); }, stop: function() { clearTimeout(this.timerId); // 清除当前的定时器 } }; myObj.myFunc(); // 500毫秒后停止并释放对象 setTimeout(() => { myObj.stop(); myObj = null; // 现在对象可以被正常回收了 }, 500);
小提醒
闭包是个好用的特性,但偶尔也会“帮倒忙”——比如意外保留引用导致内存泄漏或者无限递归。记住:只要闭包里还拿着对象的引用,哪怕外部变量被重新赋值,原对象也不会被垃圾回收哦。
内容的提问来源于stack exchange,提问作者suchcodemuchwow
相关产品推荐
相关产品推荐

