IE8兼容问题(1)

背景

今天在做项目时发现IE8的console.log返回错误,以及IE8不支持getElementsByClassName方法,并且在对document.getElementByClassName赋值给变量后无法调用,因此写下本篇文章用于记录今日的问题,并且探究问题的解决方案。

问题

1.console.log返回错误

<script>
    console.log(1);
</script>

以上代码段运行在IE8/9内核环境下会返回console未定义异常。😫

IE8 console错误截图

但是在我打开F12开发者工具之后刷新页面又不会出现以上异常,这让我烦恼不已。然后在网络上搜索资料发现IE8/9在开启开发者工具时不会构造console对象,因此会出现异常。

解决方案:

1.删除在程序内部的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

今日做开发的时候写了一个IE8的兼容实现,在对DOM操作时使用了document.getElementsByClassName来获取对象,然而却返回了错误,当时一脸懵逼,没想到IE8连如此通用的方法都没支持,先撒撒气,然后就查看兼容性实现方法。。。😢

//所书写的代码段
var delegator = documents.getElementsByClassName('content-left')[0],//报错
      isIE = typeof document.all === 'undefined'?false:true;//判断是否是IE
if(isIE){
IEFunc();               
}
else{
OtherFunc();
}
解决方案:

1.通过自实现的代码解决方案(大多参考网上的解决方案)。

//通过遍历所有标签进行判断处理(粗暴的处理方式,在对于大量标签页面的处理明显是不可取的)
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.其他大神或者框架的处理方案。(本小节内容多摘自司徒正美的博客)
The Ultimate getElementsByClassName方案,作者为Robert Nyman,05年实现。

//三个参数都是必需的,查找一网页中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|$)");
    //用于判断类名的正则,匹配开头或空格+类名+空格或结尾

    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'。

另一个实现,由Dustin Diaz(《JavaScript Design Patterns》的作者)提供,但兼容性不如上面的,不支持IE5。

//后两参数是可靠的,查找一网页中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,效率一般般,但作为最早的框架之一,它已经做得很好,其他框架还没有想到这个呢!

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;
}

后续还介绍了DOMTreeWalker 和 XPath的解决方案,但是我还没又这方面的知识就不在此处贴出了,感兴趣的同学可以浏览上面司徒正美的博客。接下来给出司徒正美前辈给出的最终解决方案:

//下列代码可以解决‘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赋值给变量后调用报错

在写兼容性代码时曾考虑将document.method赋值给变量的方式来返回兼容性结果,然而在chrome浏览器运行时异常抛出Illegal invocation

//测试代码
var getClass = document.getElementsByClassName;
getClass('class');
chrome错误内容

然而在IE8下运行上述方法奇迹般的成功了。。。😢

IE8内核下运行结果

IE9下测试则报错。

IE9内核下运行结果

而在chrome下使用

 getClass.call(document,'class'); //运行成功 图片就不上了 有兴趣的同学可以自己测试

然而非设置this为document而未其他Dom节点时就会报错,其中细节搜索资料并为找到原因,如果有大牛还请讲解原由。🙏

总结

上面总结了今日所遇到的IE8兼容性问题,有自己探索的结果也有网上搜罗的资料,虽然有些内容没有啥可用性但是作为程序员一定要有专研和探究的精神。😄 如上述问题有错误或还请大牛贴上讲解地址或者留言,感激不敬🙏,本文目的在于分享与交流,如要引用还望指明出处,谢谢。
转眼间要12点了,第一次写如此长的文章😊,希望记录今日的问题,该洗洗睡了,明天还要上班咧😄。
行文仓促,如有问题还望指出。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,718评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,683评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,207评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,755评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,862评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,050评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,136评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,882评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,330评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,651评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,789评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,477评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,135评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,864评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,099评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,598评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,697评论 2 351

推荐阅读更多精彩内容

  • DOM DOM内容主要分为四部分: 什么是DOM和节点; 获取节点; 节点操作(3种); 属性操作(3种)。 什么...
    magic_pill阅读 772评论 0 1
  • 本博客转自:「作者:若愚链接:https://zhuanlan.zhihu.com/p/22361337来源:知乎...
    韩宝亿阅读 2,757评论 0 3
  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 7,729评论 2 17
  • 参加了人人都是产品经理组织的2天产品大会,坐标深圳宝安。按照这两天嘉宾分享整理的一些分享内容和个人看法。收获满满,...
    小林同学90阅读 434评论 0 1
  • “炫耀性消费”是指富裕的上层阶级通过对物品的超出实用和生存所必需的浪费性、奢侈性和铺张浪费,向他人炫耀和展示自己的...
    晓妮臆空间阅读 2,322评论 0 1