尽管各大浏览器厂商都在努力统一接口标准,但现实是每家浏览器都有自己的长处与不足。即便版本相同,跨平台环境下的差异依然会让开发者头疼。这些不一致迫使 Web 开发者要么面向最大公约数设计,要么采用各种手段来检测客户端,以规避缺陷。
客户端检测在 Web 开发领域一直是个充满争议的话题。理想状态下,所有浏览器都应支持一套公共特性,但现实中那些莫名其妙的行为让检测变成了一种必要的补救措施,甚至成了开发策略的一部分。好在如今浏览器间的差异相比 IE 时代已大幅缩小,但不一致性仍是常态。
检测浏览器的方法五花八门,各有优劣。关键在于明确一点:客户端检测应该是解决问题的最后手段。只要存在更普适的方案,就应毫不犹豫地选择。设计时先考虑通用方案,再针对特定浏览器做兼容处理。
能力检测(Feature Detection)
能力检测,也叫特性检测,就是在 JavaScript 运行时通过简单的逻辑判断,测试浏览器是否支持某种特性。这种方式不需要事先知道浏览器的具体信息,只关心你需要的功能是否存在。基本模式通常长这样:
if (object.propertyInQuestion) {
// 使用 object.propertyInQuestion
}
比如,IE5 之前的版本中没有 document.getElementById() 这个 DOM 方法,但可以通过 document.all 属性实现同样的功能。为此,可以进行如下能力检测:
function getElement(id) {
if (document.getElementById) {
return document.getElementById(id);
} else if (document.all) {
return document.all[id];
} else {
throw new Error("No way to retrieve element!");
}
}
这个 getElement() 函数旨在通过 ID 获取 DOM 元素。因为标准方式是 document.getElementById(),所以优先测试它。如果该属性存在(非 undefined),直接使用;否则检查 document.all。如果两者都不存在(这种情况极少见),则抛出错误。
做好能力检测,得吃透两个关键点。首先,优先检测最通用的方式。就像上面的例子,先查 getElementById 再查 document.all。测试常用方案能优化执行效率,毕竟大多数情况下都能直接命中。
其次,必须检测真正需要的特性。某个能力存在不代表其他能力也存在。看下面这个反例:
function getWindowWidth() {
if (document.all) { // 假设 IE
..;
} {
.;
}
}

