获取真实的IE版本(转)

 

判断真正的 IE 版本

很多 JS 框架都通过 UA 判断 IE 的版本。对于 IE6,这种做法没问题( IE6 没有浏览器模式的概念,也没有其它 IE 可以把浏览器模式改为 IE6IE7 虽然也没有浏览器模式,但 IE8+ 可以把浏览器模式设置为IE7 模式)。但是从 IE8 开始引入的浏览器模式会产生不同的 UA。例如,IE9 有这些:

浏览器模式

navitor.userAgent

默认文本模式

IE7

MSIE 7.0

IE7标准

IE8

MSIE 8.0 && Trident/4.0

IE8标准

IE9

MSIE 9.0 && Trident/5.0

IE9标准

IE9兼容性

MSIE 7.0 && Trident/5.0

IE7标准

如果仅通过 UA 中的「MSIE X.0」来判断,会得到 IE7~9 三种不同结果。

实际上,对于 IE8+,根据 UA 字符串只能确定当前是否是兼容性视图。因为兼容性视图的 UA 中,IE 版本和 Trident 版本不匹配。例如 UA 里同时有「MSIE 7.0」和「Trident/6.0」,说明浏览器模式肯定是IE10兼容性。这是因为 IE8 才开始给 UA 加上 Trident 信息,而 Trident/6.0 IE10 所特有。

除此之外,上面 IE7  IE8 这两种浏览器模式,UA 和跟真正的 IE7 IE8 没有任何区别,根据 UA 完全没办法区分。甚至连 IE9 模式,我们也无法确认这是 IE9 浏览器的默认模式,还是 IE10 浏览器的 IE9模式。

下面来看看文本模式,依然用 IE9 测试。选择不同的文本模式,documentMode 的值也不一样。

文本模式

document.documentMode

IE7标准

7

IE8标准

8

IE9标准

9

IE5怪异Quirks

5

document.documentMode 这个 JS 属性是 IE8 引入的,对于 IE8+ 无论选择什么文本模式,这个属性都有值。而 IE6 IE7 下,这个属性是 undefined。根据这一点,可以结合 UA 判断出用户使用的是不是真正的 IE7UA 包含 IE7 时,如果 documentMode 等于 undefined,就一定是真正的 IE7 浏览器。对于 IE8+,这种方法就力不从心。例如 IE10 在浏览器模式为 IE8,文本模式为 IE8标准 时,与真正的 IE8 比较,无论是 UA,还是 document.documentMode,都一模一样。

综上,我们可以通过检查 UA Trident 版本和 IE 版本是否匹配,来判断浏览器是否工作在兼容性视图模式下。结合 document.documentMode,还可以判断出用户是否使用真正的 IE7 浏览器。

JScript 引擎版本号

JScript IE JS 引擎,IE 提供了一系列 JS 接口来获取它的 JScript 信息:

函数

返回值

ScriptEngine()

JS 中固定返回「JScript

ScriptEngineMajorVersion()

大版本号

ScriptEngineMinorVersion()

小版本号

ScriptEngineBuildVersion()

内部版本号

我用这些接口测试了 IE6~10,发现 JScript 的版本号只与浏览器有关,与浏览器的浏览器模式或文档模式无关。

浏览器

JScript 版本号

IE6

5.6.8827

IE7

5.7.22145

IE8

5.8.18702

IE9

9.0.16434

IE10

10.0.16521

忽略内部版本号,只关注前两个数字,我们会发现,从 IE9 JS 引擎换成 Chakra 开始,版本号的规律变了。令人欣慰的是,不同的 JScript 版本号对应着不同版本的浏览器,这对判断出真正的 IE 版本很有帮助。例如,要识别低于 IE8 的浏览器,下面这样写就可以了。

if(ScriptEngineMinorVersion() != 0 && ScriptEngineMinorVersion < 8) {

    //这是 IE8-

}

实际上,IE 支持的条件编译功能中,有个表示 JScript 版本的条件编译变量,如下(完整的条件编译变量清单见这里):

<script type="text/javascript">

    /*@cc_on

     alert(@_jscript_version);

    @*/

</script>

这个变量是「major.minor」格式的 JScript 版本号,跟使用 JS 接口获取到的版本号一致,也只取决于浏览器版本,不受浏览器模式和文本模式的影响。

文本模式对 JScript 没影响?

看完上一节,再看我之前写的这段:文本模式决定:1)排版引擎;2JS引擎,有明显的矛盾。难道之前的结论有误?

实际上,JS 获取到的 JScript 版本号仅仅表示了当前浏览器自带的 JScript 引擎版本(例如 IE9 始终是 9.0IE7 始终是 5.7),并不代表任何情况都可以使用这个版本 JS 引擎的所有功能,页面使用哪种版本的 JScript 引擎还是由页面的文本模式来决定

例如,IE8 JScript 版本是 5.8,但是只有在文本模式等于 IE8标准 时才可以使用 JScript5.8 的功能,其它任何文本模式都会导致页面使用 JScript5.7

举个例子,JScript5.8 增加了对 JSON 的支持,所以 IE8 支持原生 JSON 对象。但网上很多人问为什么在 IE8/9 下无法使用原生 JSON。一种可能是页面没写 DTD,导致页面进入了 IE5怪异 这种文本模式,进而启用了不支持原生 JSON JScript5.7 导致的。

再举几个例子:[,].length JScript9.0 之前是 2[1,2,3].join(undefined) JScript5.8 之前是"1undefined2undefined3"。把 IE9 的文本模式分别改成 IE9标准IE8标准  IE7标准,可以得到下表:

文本模式

[,].length

[1,2,3].join(undefined)

使用的 JScript 版本

IE7标准

2

"1undefined2undefined3"

5.7

IE8标准

2

"1,2,3"

5.8

IE9标准

1

"1,2,3"

9.0

类似的例子还有很多。大部分情况下,页面使用的 JScript 引擎版本会随着文本模式的降低而退化,页面对 JS 的支持度也随之退化。但教主 franky 提供了一个「for in顺序」的反例:

var o = {1 : '0', 0 : '1'}; for(var i in o) { console.log(i); }

对于 IE9+ 浏览器,这行代码输出顺序始终是 0 1;对于 IE9 以下的浏览器,输出顺序都是 1 0,并不受文本模式的影响。关于这一点我没想到比较好的解释。

一些 DOM 相关的方法,如 document.querySelectorAll,在文本模式为 IE7标准IE5怪异 时不可用;addEventListener 在文本模式为 IE8标准IE7标准IE5怪异 时不可用。这说明 IE 浏览器对 DOM 的支持度也会随着文本模式的降低而退化。

但是一些 BOM 方法,却跟文本模式无关。例如 IE8 开始支持的 postMessage localStorage,只要浏览器是 IE8+,无论什么文本模式,这两个功能都可用。IE9+ 支持的 window.performance,在 IE9+ 浏览器上,也始终可用,跟当前的文本模式无关。

小结下:随着文本模式的降低,页面上实际使用的 JScript 引擎会退化,一些高版本支持的语言特性不再可用(如 JSON),但 for in 的顺序问题似乎不会退化;DOM 相关功能也有相应的退化;但大部分 BOM 接口却不会退化(如 localStorage)。

总结

本文讨论的内容在各部分都小结过,最后只说一个结论:在解决 JS 兼容性问题时,一定要使用能力检测和特性检测。因为无论是从 UA 中得到的浏览器信息,还是从 JS 接口中获取到的 JScript 引擎版本,都非常不可靠。例如 UA 中包含 IE7,并不一定不支持 IE9+ window.performace。也可能是 IE9 浏览器使用了 IE9兼容性视图UA 确实会变成 IE7,文本模式为 IE7标准,但不影响对 window.performace 的支持。

另外,虽然 IE 的浏览器模式和文本模式非常复杂,组合起来有几十种情况,但大部分情况只能通过开发者工具来构造。例如 UA 中包含 IE9,实际上使用 JScript5.7 的情况(浏览器模式为 IE9,文本模式为IE7标准),正常情况下不会出现。

posted on 2016-10-14 15:45  LeLe.xu  阅读(522)  评论(0编辑  收藏  举报

导航