背景
今天在做項目時發(fā)現(xiàn)IE8的console.log返回錯誤愉舔,以及IE8不支持getElementsByClassName方法蜡吧,并且在對document.getElementByClassName賦值給變量后無法調(diào)用荐吉,因此寫下本篇文章用于記錄今日的問題木张,并且探究問題的解決方案稠鼻。
問題
1.console.log返回錯誤
<script>
console.log(1);
</script>
以上代碼段運(yùn)行在IE8/9內(nèi)核環(huán)境下會返回console未定義異常捺信。??
但是在我打開F12開發(fā)者工具之后刷新頁面又不會出現(xiàn)以上異常刃滓,這讓我煩惱不已仁烹。然后在網(wǎng)絡(luò)上搜索資料發(fā)現(xiàn)IE8/9在開啟開發(fā)者工具時不會構(gòu)造console對象,因此會出現(xiàn)異常咧虎。
解決方案:
1.刪除在程序內(nèi)部的console對象
2.為console對象初賦值卓缰。
//將console對象在console未定義時初始化為一個空方法對象,避免IE8/9報錯
window.console=window.console||(function(){
var c = {};
c.log=c.info=c.assert=c.error=c.dir=c.clear=c.profile=c.warn=
c.profileE=function(){}
return c;
})();
2.IE8不支持document.getElementsByClassName
今日做開發(fā)的時候?qū)懥艘粋€IE8的兼容實現(xiàn)砰诵,在對DOM操作時使用了document.getElementsByClassName來獲取對象征唬,然而卻返回了錯誤,當(dāng)時一臉懵逼茁彭,沒想到IE8連如此通用的方法都沒支持鳍鸵,先撒撒氣,然后就查看兼容性實現(xiàn)方法尉间。偿乖。。??
//所書寫的代碼段
var delegator = documents.getElementsByClassName('content-left')[0],//報錯
isIE = typeof document.all === 'undefined'?false:true;//判斷是否是IE
if(isIE){
IEFunc();
}
else{
OtherFunc();
}
解決方案:
1.通過自實現(xiàn)的代碼解決方案(大多參考網(wǎng)上的解決方案)哲嘲。
//通過遍歷所有標(biāo)簽進(jìn)行判斷處理(粗暴的處理方式贪薪,在對于大量標(biāo)簽頁面的處理明顯是不可取的)
document.getElementsByClassName = document.getElementsByClassName||function(value){
var arr = [];
var all = document.getElementsByTagName('*');
for(var i=0,len=all.length;i<len;i++){
var temp = all[i].getAttribute('class');
if(temp&&temp.indexOf(value)>=0){
arr.push(all[i]);
}
}
return arr;
};
2.其他大神或者框架的處理方案。(本小節(jié)內(nèi)容多摘自司徒正美的博客)
The Ultimate getElementsByClassName方案眠副,作者為Robert Nyman画切,05年實現(xiàn)。
//三個參數(shù)都是必需的囱怕,查找一網(wǎng)頁中5007個類名為“cell”的元素霍弹,IE8歷時1828 ~ 1844毫秒
function getElementsByClassName(oElm, strTagName, strClassName){
//oElm DOM對象,strTagName 查找對象的Tag名,strClassName 查找對象的類名
var arrElements = (strTagName == "*" && oElm.all)? oElm.all :
oElm.getElementsByTagName(strTagName);
//oElm.all可獲取所有DOM對象, (Tips1)
var arrReturnElements = new Array();
strClassName = strClassName.replace(/\-/g, "\\-");
var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
//用于判斷類名的正則,匹配開頭或空格+類名+空格或結(jié)尾
var oElement;
for(var i=0; i < arrElements.length; i++){
oElement = arrElements[i];
if(oRegExp.test(oElement.className)){
arrReturnElements.push(oElement);
}
}
return (arrReturnElements);
}
Tips1:typeof document.all 在IE下返回'object'娃弓,在其他瀏覽器下返回'undefined'典格。
另一個實現(xiàn),由Dustin Diaz(《JavaScript Design Patterns》的作者)提供台丛,但兼容性不如上面的耍缴,不支持IE5。
//后兩參數(shù)是可靠的,查找一網(wǎng)頁中5007個類名為“cell”的元素防嗡,IE8歷時78毫秒变汪,IE6歷時125~171毫秒
var getElementsByClass = function(searchClass,node,tag) {
var classElements = new Array();
if ( node == null )
node = document;
if ( tag == null )
tag = '*';
var els = node.getElementsByTagName(tag);
var elsLen = els.length;
var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
for (i = 0, j = 0; i < elsLen; i++) {
if ( pattern.test(els[i].className) ) {
classElements[j] = els[i];
j++;
}
}
return classElements;
}
還有個更古老級的,司徒正美前輩從prototype.js1.01版本中找到的蚁趁,它能支持多個類名的查找(上面兩個不行)裙盾。它不支持IE5,效率一般般他嫡,但作為最早的框架之一闷煤,它已經(jīng)做得很好,其他框架還沒有想到這個呢涮瞻!
function getElementsByClassName(className, element) {
var children = (element || document).getElementsByTagName('*');
var elements = new Array();
for (var i = 0; i < children.length; i++) {
var child = children[i];
var classNames = child.className.split(' ');
for (var j = 0; j < classNames.length; j++) {
if (classNames[j] == className) {
elements.push(child);
break;
}
}
}
return elements;
}
后續(xù)還介紹了DOMTreeWalker 和 XPath的解決方案鲤拿,但是我還沒又這方面的知識就不在此處貼出了,感興趣的同學(xué)可以瀏覽上面司徒正美的博客署咽。接下來給出司徒正美前輩給出的最終解決方案:
//下列代碼可以解決‘red cell’ 對<span class="cell red"></span>等特殊class情況的檢索
var getElementsByClassName = function (searchClass, node,tag) {
if(document.getElementsByClassName){
var nodes = (node || document).getElementsByClassName(searchClass),result = [];
for(var i=0 ;node = nodes[i++];){
if(tag !== "*" && node.tagName === tag.toUpperCase()){
result.push(node)
}
}
return result
}else{
node = node || document;
tag = tag || "*";
var classes = searchClass.split(" "),
elements = (tag === "*" && node.all)? node.all : node.getElementsByTagName(tag),
patterns = [],
current,
match;
var i = classes.length;
while(--i >= 0){
patterns.push(new RegExp("(^|\\s)" + classes[i] + "(\\s|$)"));
}
var j = elements.length;
while(--j >= 0){
current = elements[j];
match = false;
for(var k=0, kl=patterns.length; k<kl; k++){
match = patterns[k].test(current.className);
if (!match) break;
}
if (match) result.push(current);
}
return result;
}
}
3.document.method賦值給變量后調(diào)用報錯
在寫兼容性代碼時曾考慮將document.method賦值給變量的方式來返回兼容性結(jié)果近顷,然而在chrome瀏覽器運(yùn)行時異常拋出Illegal invocation
//測試代碼
var getClass = document.getElementsByClassName;
getClass('class');
然而在IE8下運(yùn)行上述方法奇跡般的成功了。宁否。窒升。??
IE9下測試則報錯。
而在chrome下使用
getClass.call(document,'class'); //運(yùn)行成功 圖片就不上了 有興趣的同學(xué)可以自己測試
然而非設(shè)置this為document而未其他Dom節(jié)點時就會報錯慕匠,其中細(xì)節(jié)搜索資料并為找到原因饱须,如果有大牛還請講解原由。??
總結(jié)
上面總結(jié)了今日所遇到的IE8兼容性問題台谊,有自己探索的結(jié)果也有網(wǎng)上搜羅的資料蓉媳,雖然有些內(nèi)容沒有啥可用性但是作為程序員一定要有專研和探究的精神。?? 如上述問題有錯誤或還請大牛貼上講解地址或者留言锅铅,感激不敬??酪呻,本文目的在于分享與交流,如要引用還望指明出處盐须,謝謝玩荠。
轉(zhuǎn)眼間要12點了,第一次寫如此長的文章??贼邓,希望記錄今日的問題阶冈,該洗洗睡了,明天還要上班咧??塑径。
行文倉促女坑,如有問題還望指出。