IE9之前的IE版本的HTMLCollection以及NodeList不是Object的子类。
在通过Array.prototype.slice.call进行数组化的时候,IE9之前的IE版本会抛出异常,因此需要进行兼容处理。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <style rel="stylesheet" type="text/css"> 6 </style> 7 <script> 8 window.onload=function(){ 9 var n=document.getElementsByTagName("div"); 10 try{ 11 document.body.innerHTML=[].slice.call(n,0); 12 } 13 catch(ex){ 14 document.body.innerHTML="ERROR:"+ex.message; 15 } 16 } 17 </script> 18 </head> 19 <body><div class="show">HELLO</div><div></div></body> 20 </html>
兼容实现需要兼容IE9一下的IE版本,动手实现slice方法,
考虑到String对象,Window对象,Function对象,RegExp对象(黑莓4.7中)都有length属性,因此需要排除。
一个可能的实现如下:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <script> 6 window.onload=function(){ 7 var n=document.getElementsByTagName("div"); 8 try{ 9 document.body.innerHTML+=[].slice.call(n,0); 10 } 11 catch(ex){ 12 document.body.innerHTML+="ERROR:"+ex.message; 13 } 14 document.body.innerHTML+="<br/>"+getA(n,0); 15 }; 16 17 var bIEltIE9=(function(){ 18 var ag=window.navigator.userAgent.toLowerCase(); 19 var reg=new RegExp("msie ([\S]+);"); 20 if(reg.test(ag)){ 21 var version=RegExp.$1; 22 if(parseInt(version)<9){ 23 return true; 24 } 25 } 26 return false; 27 })(); 28 29 var getA=function(a,start,end){ 30 if(a==null){ 31 return []; 32 } 33 if(!bIEltIE9){ 34 try{ 35 return [].slice.call(a,start,end); 36 } 37 catch(ex){} 38 } 39 var ret=[]; 40 var i=a.length; 41 // 如果为空或者为字符串或者为函数或者为window对象或者为RegExp 42 if(i==null||typeof a ==="string"||typeof a==="function"||a.setInterval||a instanceof RegExp){ 43 ret[0]=a; 44 } 45 else{ 46 while(i){ 47 ret[--i]=a[i]; 48 } 49 } 50 return ret; 51 52 }; 53 54 </script> 55 </head> 56 <body><div class="show">数组化</div><div></div></body> 57 </html>
上面代码的function和window判断不严瑾,具体参考:JavaScript 类型判断 —— typeof 以及 instanceof 中的陷阱。
更多可以参考:
- 《JavaScript框架设计 司徒正美》P4 数组化。
- 《JQuery技术内幕》P68 数组操作方法。