一年半之前我写了一篇《关于浏览器模式和文本模式的困惑》,介绍了IE8+特有的浏览器模式(Browser Mode)和文本模式(Document Mode),以及我的测试和微软文档有出入的部分。其中有一些没有提到的内容,本文继续讨论。
判断真正的IE版本很多JS框架都通过UA判断IE的版本。对于IE6,这种做法没问题(IE6没有浏览器模式的概念,也没有其它IE可以把浏览器模式改为IE6;IE7虽然也没有浏览器模式,但IE8+可以把浏览器模式设置为IE7模式)。但是从IE8开始引入的浏览器模式会产生不同的UA。例如,IE9有这些:
[table]
[tr][td]浏览器模式[/td][td]navitor.userAgent[/td][td]默认文本模式[/td][/tr]
[tr][td]IE7[/td][td]MSIE 7.0[/td][td]IE7标准[/td][/tr]
[tr][td]IE8[/td][td]MSIE 8.0 && Trident/4.0[/td][td]IE8标准[/td][/tr]
[tr][td]IE9[/td][td]MSIE 9.0 && Trident/5.0[/td][td]IE9标准[/td][/tr]
[tr][td]IE9兼容性[/td][td]MSIE 7.0 && Trident/5.0[/td][td]IE7标准[/td][/tr]
[/table]如果仅通过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的值也不一样。
[table]
[tr][td]文本模式[/td][td]document.documentMode[/td][/tr]
[tr][td]IE7标准[/td][td]7[/td][/tr]
[tr][td]IE8标准[/td][td]8[/td][/tr]
[tr][td]IE9标准[/td][td]9[/td][/tr]
[tr][td]IE5怪异(Quirks)[/td][td]5[/td][/tr]
[/table]document.documentMode这个JS属性是IE8引入的,对于IE8+无论选择什么文本模式,这个属性都有值。而IE6和IE7下,这个属性是undefined。根据这一点,可以结合UA判断出用户使用的是不是真正的IE7:UA包含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信息:
[table]
[tr][td]ScriptEngine()
[/td][td]JS中固定返回“JScript”[/td][/tr]
[tr][td]ScriptEngineMajorVersion()
[/td][td]大版本号[/td][/tr]
[tr][td]ScriptEngineMinorVersion()[/td][td]小版本号[/td][/tr]
[tr][td]ScriptEngineBuildVersion()[/td][td]内部版本号[/td][/tr]
[/table]我用这些接口测试了IE6~10,发现JScript的版本号只与浏览器有关,与浏览器的浏览器模式或文档模式无关。
[table]
[tr][td]浏览器[/td][td]JScript版本号[/td][/tr]
[tr][td]IE6[/td][td]5.6.8827[/td][/tr]
[tr][td]IE7[/td][td]5.7.22145[/td][/tr]
[tr][td]IE8[/td][td]5.8.18702[/td][/tr]
[tr][td]IE9[/td][td]9.0.16434[/td][/tr]
[tr][td]IE10[/td][td]10.0.16521[/td][/tr]
[/table]忽略内部版本号,只关注前两个数字,我们会发现,从IE9把JS引擎换成Chakra开始,版本号的规律变了。令人欣慰的是,不同的JScript版本号对应着不同版本的浏览器,这对判断出真正的IE版本很有帮助。例如,要识别低于IE8的浏览器,下面这样写就可以了。
if(ScriptEngineMinorVersion() != 0 && ScriptEngineMinorVersion < 8) { //ie8- browser}实际上,IE支持的条件编译功能中,有个表示JScript版本的条件编译变量,如下(完整的条件编译变量清单见这里):
文本模式对JScript没影响?看完上一节,再看我之前写的这段:文本模式决定:1)排版引擎;2)JS引擎,有明显的矛盾。难道之前的结论有误?
实际上,JS获取到的JScript版本号仅仅表示了当前浏览器自带的JScript引擎版本(例如IE9始终是9.0,IE7始终是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标准,可以得到下表:
[table]
[tr][td]文本模式 [/td][td][,].length[/td][td][1,2,3].join(undefined)[/td][td]使用的JScript版本[/td][/tr]
[tr][td]IE7标准[/td][td]2[/td][td]“1undefined2undefined3”
[/td][td]5.7[/td][/tr]
[tr][td]IE8标准[/td][td]2[/td][td]“1,2,3”
[/td][td]5.8[/td][/tr]
[tr][td]IE9标准[/td][td]1[/td][td]“1,2,3”
[/td][td]9.0[/td][/tr]
[/table]类似的例子还有很多。大部分情况下,页面使用的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标准),正常情况下不会出现。
参考:
[list]
[]How Internet Explorer 8 document mode affects JavaScript
[]Same Markup: Explaining “@_jscript_version” and Styling New HTML5 Elements
[]Versioning Language Features in JScript
[]IE9的特性变化 By Franky
[/list]本文链接:http://www.imququ.com/post/browser-mode-and-document-mode-in-ie-2.html
–EOF–