由 IE8 User-Agent 更新想到的

作者:手气不错 发布时间:January 11, 2009 分类:JavaScript

IE 开发团队更改了 IE8 的 User-agent ,更改的部分信息如下:

IE8 on Windows Vista (Compatibility View)
    Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0) 

IE8 on Windows Vista
    Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)

除了 IE8 因 Compatibility View 功能造成单浏览器“原生”多个 User-agent 外,还有个情况也变得非常的有趣,就是几乎每个浏览器都将自己渲染引擎的标识加入到了 User-agent 中(Gecko、WebkitTrident)。

User-agent 信息常被用作检测浏览器类型和版本的最佳途径(YUIjQuery),而上述的改动是否意味着以后类似的检测脚本会变得更加的复杂?回答这个问题之前,让我们看下 Mootools 如何检测浏览器信息

var Browser = {
    Engine: {name: 'unknown', version: 0},
    Features: {
        xpath: !!(document.evaluate),     // 是否支持 XPath
          air: !!(window.runtime),        // 是否支持 Air 扩展
        query: !!(document.querySelector) // 是否支持 CSS 选择器
    },
    Engines: {
        // 判断 Opera
        presto: function() {
            return (!window.opera) ? 
                false : ((arguments.callee.caller) ? 
                    960 : ((document.getElementsByClassName) ? 950 : 925));
        },
        // 判断 IE,根据 ActiveX 和 特有的 XMLHttpRequest 对象
        trident: function() {
            return (!window.ActiveXObject) ? 
                           false : ((window.XMLHttpRequest) ? 5 : 4);
        },
        // Webkit 核心的浏览器,如 Safari 和 Chrome
        webkit: function() {
            return (navigator.taintEnabled) ? 
                false : ((Browser.Features.xpath) ? 
                    ((Browser.Features.query) ? 525 : 420) : 419);
        },
        // Mozilla Gecko 核心浏览器,如 Firefox
        gecko: function() {
            return (document.getBoxObjectFor == undefined) ?
                false : ((document.getElementsByClassName) ? 19 : 18);
        }
    }
};

Browser.detect = function() {
    for (var engine in this.Engines){
        var version = this.Engines[engine]();
        // 如果具有特定的浏览器对象
        if (version){
            this.Engine = {name: engine, version: version};
            this.Engine[engine] = this.Engine[engine + version] = true;
            break;
        }
    }
    return {name: engine, version: version};
};

Browser.detect();

上述代码让人感到耳目一新,它是根据浏览器功能而非 User-agent 判断浏览器类型。仔细考虑一下,User-agent 信息可以被伪造,同时浏览器厂商日后也会更改 User-agent 信息,所以此种情况下根据功能判断浏览器类型会可靠得多。

延伸下此策略,比如我们会编写这样的代码:

if (ie) {
  // ie only
} else {
  // other browsers
}

这样因浏览器差异而编写的“硬代码”,往往会造成维护两套实际相同功能的代码,并造成逻辑上的混乱。何不先抛开浏览器兼容的问题,然后再判断相应的对象是否被浏览器支持。

OK,有关编程思想的问题就不继续了…

-- Split --

PS,目前判断是否是 IE8 可这样编写(来自 舜子):

var isIE8 = !!window.XDomainRequest;

已有 7 条回复

  1. dexbol January 11th, 2009 at 05:31 pm #1
    dexbol

    够快,昨天晚上才在ie blog上看到这条消息。

  2. 阿肆 January 11th, 2009 at 07:59 pm #2
    阿肆

    ppk on javascript 上前面就谈了这个问题,强烈建议不要通过User-agent来判断浏览器的。

  3. Wasabi January 11th, 2009 at 11:31 pm #3
    Wasabi

    IE8还没用过......



    个人觉得,判断User-agent还真不是好主意~~~

  4. 秦歌 January 12th, 2009 at 07:13 am #4
    秦歌

    jQuery1.3已经不基于UA了.

  5. 手气不错 January 13th, 2009 at 08:30 am #5
    手气不错

    @秦歌 没找到相关的代码,我看到的是这个



    http://dev.jquery.com/browser/trunk/jquery/src/core.js#L1138

  6. heluyao January 14th, 2009 at 08:18 pm #6
    heluyao

    判断相应的对象是否被浏览器支持,应该就够了。关于浏览器检测,个人认为没必要基本不需要用到。

  7. 如何检测IE8 » awman June 22nd, 2009 at 11:38 am #7
    如何检测IE8 »  awman

    [...]单纯从检测浏览器的版本来说,userAgent对IE8已经不再可靠,原因是IE8加入了兼容性试图功能,导致IE8出现多个userAgent。详细查看gracecode的《由IE8 User-Agent 更新想到的》一文[...]

Yahoo 统计