备忘:递归callee.caller导致死循环
今天网友 Baobao包子 反映QWrap里的QW.EventH.getEvent有可能会产生死循环。
代码如下:
/** * 获得event对象 * @method getEvent * @param {event} event (Optional)event对象 默认为调用位置所在宿主的event * @param {element} element (Optional)任意element对象 element对象所在宿主的event * @return {event} event对象 */ getEvent: function(event, element) { if (event) { return event; } else if (element) { if (element.document) {return element.document.parentWindow.event; } if (element.parentWindow) {return element.parentWindow.event; } } if (window.event) { return window.event; } else { var f = arguments.callee; do { if (/Event/.test(f.arguments[0])) {return f.arguments[0]; } } while (f = f.caller); } },
网友 集鹄 也曾在2011-12-07以一个例子来说过这个死循环的问题:
var getEvent_Count = 0; function getEvent(e) { e = e || window.event; if (!e) { var c = arguments.callee.caller; while (c) { if (getEvent_Count++ > 1000) { alert('死循环了!'); return; } e = c.arguments[0]; if (e && typeof (e.altKey) == "boolean") { // duck typing break; } c = c.caller; e = null; } } return e; } function test(n) { return n ? test(n - 1) : getEvent(); } test(2);
造成死循环的原因:caller链中有时会有闭环。例如:一个function的caller有可能等于本身。
另:QW.EventH.getEvent 方法并不直接对业务编码的同学开放,目前还没有人踩坑,暂无必要更改实现方法。