解决 IE6 IE7 onresize的bug

本文介绍了解决IE浏览器中window.onresize事件触发频繁的问题,通过使用debounce函数进行防抖处理,有效避免了事件处理函数被重复调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

IE下给window对象定义其onresize事件,在拉伸缩小窗口时,其onresize方法将被执行多次,并且其具体执行的次数在不同的电脑有不同的值,相当诡异,Firefox等其他浏览器则无此现象。具体可参看这一篇文章《window.onresize hangs IE6 and IE7》

高阶函数debounce 正是为此而生的


 

[javascript]  view plain copy
  1. /** 
  2.  * IE下 window.onresize 有bug 可以使用debounce封装监听函数  
  3.  * see http://blog.youkuaiyun.com/fudesign2008/article/details/7035537 
  4.  * @author FuDesign2008@163.com 
  5.  * @date   2011-11-30 
  6.  * @time   下午04:02:55 
  7.  */  
  8.   
  9. /** 
  10.  * 
  11.  * @param {Function} callback 回调函数 
  12.  * @param {Integer} delay   延迟时间,单位为毫秒(ms),默认150 
  13.  * @param {Object} context  上下文,即this关键字指向的对象,默认为null 
  14.  * @return {Function} 
  15.  */  
  16. function debounce(callback, delay, context){  
  17.     if (typeof(callback) !== "function") {  
  18.         return;  
  19.     }  
  20.     delay = delay || 150;  
  21.     context = context || null;  
  22.     var timeout;  
  23.     var runIt = function(){  
  24.             callback.apply(context);  
  25.         };  
  26.     return (function(){  
  27.         window.clearTimeout(timeout);  
  28.         timeout = window.setTimeout(runIt, delay);  
  29.     });  
  30. }  
  31. var winResizeHandler = function(event){  
  32.       console.log("window resized");  
  33. };  
  34.   
  35. window.onresize= debounce(winResizeHandler, 300);  

非常不错的解决方案
<think>我们正在使用JavaScript检测浏览器是否为Internet Explorer(IE)。由于用户代理字符串(userAgent)可能被修改,且不同浏览器可能包含相似字符串,因此需要谨慎处理。 引用[1]提到:如果先检查"MSIE"可能会误判,因为Opera的userAgent可能包含"MSIE"。因此,应该先检查Opera,然后再检查其他浏览器。 引用[2]也提到了区分IE和其他浏览器的方法。 另外,IE11开始,用户代理字符串中不再包含"MSIE",而是使用"Trident"引擎标识。因此,我们需要同时检查"MSIE"和"Trident"。 根据上述信息,我们可以设计一个函数来检测IE浏览器(包括IE11及以后版本)。注意,Edge浏览器虽然也使用Trident引擎(旧版Edge),但新版Edge已经使用Chromium引擎,并且用户代理字符串中不再包含"MSIE"或"Trident"。但为了兼容旧版Edge(EdgeHTML引擎),我们可能需要排除Edge。 然而,用户的问题只要求检测Internet Explorer,不包括Edge(因为Edge是另一个浏览器)。因此,我们只关注IE。 思路: 1. 首先检查浏览器是否为Opera(因为Opera可能包含"MSIE"字符串),如果是则不是IE。 2. 然后检查用户代理字符串中是否包含"MSIE"(IE10及以下)或"Trident"(IE11及以上)。 但是,注意引用[1]中建议先检查Opera,但现代Opera可能已经不再包含"MSIE",但我们仍然遵循这个原则。 另一种更可靠的方法是使用条件注释(仅适用于IE10及以下),但这种方法只能在HTML中使用,在JavaScript中无法直接使用。 因此,我们使用用户代理字符串检测,并注意排除其他浏览器。 考虑到Edge的用户代理字符串中包含"Edg"(新版Edge)或"Edge"(旧版Edge),并且旧版Edge也包含"Trident",所以我们需要排除包含"Edge"或"Edg"的情况。 所以,我们可以这样写: - 如果用户代理字符串中包含"MSIE"(不包括"Edge"或"Edg"),则为IE - 或者,如果用户代理字符串中包含"Trident",并且不包含"Edge"(旧版Edge)和"Edg"(新版Edge),则为IE 注意:由于新版Edge(Edg)已经使用Chromium,其用户代理字符串中不再包含"Trident",所以我们只需要排除旧版Edge(用户代理字符串中有"Edge")。 因此,我们可以定义一个函数: 注意:我们也可以使用更简单的方法,因为旧版Edge的用户代理字符串中同时包含"Trident"和"Edge",所以我们可以通过检查"Trident"并且不包含"Edge"来判断是否为IE(因为IE的Trident没有"Edge")。 具体代码: ```javascript function isIE() { var ua = window.navigator.userAgent; // 检查是否为Opera,但现代Opera已经不再包含"MSIE",所以这一步可以省略?但为了遵循引用[1]的建议,我们检查Opera // 但注意,现代Opera的用户代理字符串中包含"OPR",所以我们可以检查"OPR"来排除Opera // 另外,也要排除Edge if (ua.indexOf("Opera") > -1 || ua.indexOf("OPR") > -1 || ua.indexOf("Edge") > -1 || ua.indexOf("Edg") > -1) { return false; } // 检查MSIE或Trident return (ua.indexOf("MSIE") > -1 || ua.indexOf("Trident") > -1); } ``` 但是,上面的排除条件可能过于宽泛,因为Opera可能不会包含"MSIE"了,而Edge我们只关心它是否包含"Edge"或"Edg"。另外,我们也可以不先排除,而是直接判断: ```javascript function isIE() { var ua = window.navigator.userAgent; // 先排除Edge/Edg(因为Edge可能包含Trident,但它是Edge不是IE) if (ua.indexOf("Edge") > -1 || ua.indexOf("Edg") > -1) { return false; } // 然后检查MSIE或Trident return (ua.indexOf("MSIE") > -1 || ua.indexOf("Trident") > -1); } ``` 但是,Opera的问题:如果Opera的userAgent包含"MSIE",我们也要排除。但现代Opera已经不再包含"MSIE",所以我们可以不考虑。但为了安全,我们可以加上Opera的检测(使用"OPR"标识)。 所以,更严谨的写法: ```javascript function isIE() { var ua = window.navigator.userAgent; // 排除Opera和Edge if (ua.indexOf("OPR") > -1 || ua.indexOf("Opera") > -1 || ua.indexOf("Edge") > -1 || ua.indexOf("Edg") > -1) { return false; } return (ua.indexOf("MSIE") > -1 || ua.indexOf("Trident") > -1); } ``` 但是,注意:Opera的旧版本可能使用"Opera"字符串,而新版本使用"OPR"。另外,有些浏览器可能同时包含多个标识,所以我们的排除条件应该覆盖所有情况。 然而,还有一种情况:有些浏览器可能会伪装成其他浏览器,但我们的目标只是普通场景。 另外,我们可以使用更简洁的方法:直接检查MSIE或Trident,同时排除Edge(因为Edge有Trident但并不是IE)和Opera(因为Opera可能包含MSIE)。但现代浏览器中,Opera已经不再包含MSIE,所以我们可以只排除Edge。 因此,我们采用: ```javascript function isIE() { var ua = window.navigator.userAgent; // 检查是否包含Edge/Edg,如果是则不是IE if (ua.indexOf("Edge/") > -1 || ua.indexOf("Edg/") > -1) { return false; } // 检查MSIE或Trident return (ua.indexOf("MSIE") > -1 || ua.indexOf("Trident") > -1); } ``` 注意:我们检查"Edge/"和"Edg/"是为了更精确,因为有些字符串可能包含"Edge"但不一定是浏览器(但可能性很小)。不过,通常检查"Edge"和"Edg"即可。 或者,我们可以使用正则表达式,但这里为了简单,使用字符串方法。 另外,引用[3]提到了一种检测元素尺寸变化的方法,其中对IE10及以下使用了onresize事件,这也间接说明检测IE的重要性。 最后,我们给出一个常用的方法,也是很多项目中使用的: ```javascript var isIE = !!document.documentMode; ``` 因为IEIE8开始支持documentMode属性,而其他浏览器没有。这是一个非常可靠的方法,但注意:只有IE5-11支持,Edge不再支持。所以,如果存在document.documentMode,那么就是IE(包括IE11)。 但是,这个方法只能在IE中使用,其他浏览器中documentMode为undefined。所以,我们可以这样写: ```javascript function isIE() { return !!document.documentMode; } ``` 这个方法更简单,而且避免了用户代理字符串的解析问题。但是,注意:在非浏览器环境(如Node.js)中,document未定义,所以需要确保在浏览器环境中运行。 因此,我们推荐使用`document.documentMode`来检测IE(包括IE8-IE11)。但是,IE7及以下不支持documentMode,所以对于IE7及以下,我们仍然需要使用用户代理字符串。 所以,为了兼容IE7及以下,我们可以结合两种方法: ```javascript function isIE() { // 对于IE8及以上,使用documentMode检测 if (document.documentMode) { return true; } // 对于IE7及以下,使用MSIE字符串检测 var ua = window.navigator.userAgent; return (ua.indexOf("MSIE") > -1); } ``` 但是,注意:在IE11中,用户代理字符串中已经移除了"MSIE",所以第一部分的documentMode可以检测到IE11。而IE7-IE10可以通过用户代理字符串中的"MSIE"检测。 另外,IE11的用户代理字符串示例: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko 所以,我们也可以只使用用户代理字符串检测所有IE(包括IE11),但需要同时检测"MSIE"和"Trident"。 然而,使用document.documentMode的方法更简洁,而且IE11以下(包括IE8、9、10)都支持document.documentMode(IE7不支持,但IE7已经非常古老)。 因此,如果不需要支持IE7,我们可以直接使用: ```javascript function isIE() { return !!document.documentMode; } ``` 如果需要支持IE7,则使用: ```javascript function isIE() { return !!document.documentMode || /MSIE/.test(navigator.userAgent); } ``` 注意:在非IE浏览器中,document.documentMode是undefined,!!undefined为false。在IE7中,document.documentMode是undefined,但用户代理字符串包含"MSIE"。 因此,我们推荐使用第二种方法(如果需要支持IE7),否则使用第一种。 考虑到现在IE7已经很少见,我们可以使用第一种方法。但为了全面性,我们也可以使用第二种方法。 另外,在IE11中,条件注释已经被移除,所以无法使用条件注释的方法。 综上所述,我们给出两种方案: 方案1(推荐,简单可靠): ```javascript function isIE() { return !!document.documentMode; } ``` 方案2(兼容更老的IE,包括IE7): ```javascript function isIE() { return !!document.documentMode || /MSIE/.test(navigator.userAgent); } ``` 但是,方案2在IE11中,由于用户代理字符串没有"MSIE",所以只靠document.documentMode(为11)返回true。在IE7-IE10中,如果document.documentMode存在(IE8+)就返回true,不存在则检查"MSIE"(IE7)。 因此,我们选择方案2。 注意:在IE5和IE6中,用户代理字符串也包含"MSIE",所以也能检测到。 但是,我们也要注意:如果用户代理字符串被修改,可能会影响检测结果。而document.documentMode是IE浏览器特有的属性,不会被修改。 所以,我们优先使用document.documentMode,因为它更可靠。 最后,我们给出完整代码,并考虑在非浏览器环境下的容错(比如在Node.js中运行会报错,因为document未定义): ```javascript function isIE() { // 确保在浏览器环境下运行 if (typeof document !== 'undefined') { return !!document.documentMode || /MSIE/.test(navigator.userAgent); } return false; // 非浏览器环境,不是IE } ``` 或者,我们可以使用更安全的写法,检查navigator是否存在: ```javascript function isIE() { // 检查是否在浏览器环境中 if (typeof window === 'undefined' || typeof navigator === 'undefined') { return false; } // 使用document.documentMode或用户代理字符串 return !!document.documentMode || /MSIE/.test(navigator.userAgent); } ``` 但是,在浏览器环境中,window和navigator都是存在的,所以我们可以简化。 因此,我们最终采用: ```javascript function isIE() { return !!document.documentMode || /MSIE/.test(navigator.userAgent); } ``` 在非浏览器环境中,如果调用这个函数,可能会因为document或navigator未定义而报错。所以,如果需要在非浏览器环境中使用,需要自行确保安全。 现在,我们回答用户的问题:如何用JavaScript检测浏览器是否为Internet Explorer。 我们推荐使用上述函数。 另外,引用[4]提到现代网络不再支持旧的IE浏览器,所以检测IE可能是为了提供降级方案或提示用户升级。 综上所述,我们给出答案。</think>要判断浏览器是否为 Internet Explorer (IE),可以使用 JavaScript 检测浏览器的用户代理字符串(User Agent)。以下是可靠的实现方法: ### 推荐代码 ```javascript function isInternetExplorer() { const ua = window.navigator.userAgent; // 检测 MSIEIE10及以下)或 Trident(IE11) const msie = ua.indexOf('MSIE ') > -1; const trident = ua.indexOf('Trident/') > -1; // 排除 Edge(旧版Edge包含Trident但需单独处理) const isEdge = ua.indexOf('Edge/') > -1; return (msie || trident) && !isEdge; } // 使用示例 if (isInternetExplorer()) { console.log("当前是 Internet Explorer 浏览器"); } else { console.log("当前不是 IE 浏览器"); } ``` ### 关键检测原理 1. **`MSIE`** IE10 及更早版本的用户代理中包含 `MSIE` 标识(如 `MSIE 10.0`)。 2. **`Trident`** IE11 的用户代理中包含 `Trident`(如 `Trident/7.0`)。 3. **排除 Edge 浏览器** 旧版 Edge(基于 EdgeHTML)的用户代理同时包含 `Trident` 和 `Edge`,需通过 `!isEdge` 排除误判[^1][^2]。 ### 其他注意事项 - **兼容性**:此方法支持 IE5~IE11 全系列检测 - **用户代理篡改**:若用户手动修改 UA 字符串可能导致检测失效 - **IE 模式检测**:Edge 浏览器中的 IE 模式需额外检查 `window.document.documentMode` 属性: ```javascript // 检测 Edge 中的 IE 模式 const isIEMode = !!window.document.documentMode; ``` ### 替代方案(推荐) IE 特有属性检测更可靠(避免 UA 篡改问题): ```javascript function isIE() { return !!window.document.documentMode; // IE8~IE11 均支持 } ``` --- ### 相关问题 1. **如何区分 IE 和 Edge 浏览器?** Edge 的 UA 包含 `Edg` 或 `Edge` 标识,而 IE 只有 `MSIE` 或 `Trident`[^2]。 2. **IE11 中为何不再使用 `MSIE` 标识?** 微软在 IE11 中移除了 `MSIE` 以避免网站锁定旧版 IE,改用 `Trident` 引擎标识[^4]。 3. **如何检测已被停用的旧版 IE(如 IE6)?** 需检查 UA 中的版本号: ```javascript const isIE6 = /MSIE 6\.0/.test(navigator.userAgent); ``` 4. **为什么优先检测 `document.documentMode`?** 该属性是 IE 特有且不可伪造,比解析 UA 更可靠[^3]。 [^1]: 先检测 Opera 可避免误判包含 "MSIE" 的非 IE 浏览器 [^2]: Edge 需单独处理以避免与 IE11 的 Trident 标识冲突 [^3]: `document.documentMode` 是 IE 特有的属性检测方式 [^4]: IE11 移除了 UA 中的 "MSIE" 以推动标准兼容
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值