浏览器检测与特性检测

45

我要做一下反对者的角色。我一直在想,为什么浏览器检测(与特性检测不同)被认为是一种绝对的坏习惯。如果我测试某个特定版本的浏览器,并确认,某些功能表现出一些可预测的方式,那么似乎决定特殊处理它是可以接受的。理由是这样做将来是不会出问题的,因为这个部分的浏览器版本不会改变。另一方面,如果我检测到 DOM 元素具有函数 X,这并不一定意味着:

  1. 这个函数在所有浏览器中都以相同的方式工作,并且
  2. 更重要的是,即使在所有未来的浏览器中也会以相同的方式工作。

我刚刚查看了 jQuery 的源代码,他们通过将精心构造的 HTML 片段插入 DOM 中进行特性检测,然后检查是否具有某些特性。这是一个明智而可靠的方法,但我想说,如果我在我的小型个人 JavaScript 中只是做类似的事情(没有使用 jQuery),那么这可能会有点过于繁重。他们也拥有几乎无限的 QA 资源的优势。另一方面,你经常看到人们检查函数 X 的存在,然后基于此,他们假设具有该函数的所有浏览器都会以某种方式运行该函数。

我并不是说特性检测不好(如果使用正确),但我想知道为什么浏览器检测通常被立即驳回,即使听起来很合理。我想知道这是否又是一个时髦的说法。


为什么我们要称之为浏览器检测呢?几乎所有其他的浏览器,包括Internet Explorer,都只想称自己为Mozilla? - webs
3个回答

29
我认为自从Resig在几年前发布了这篇文章之后,浏览器检测似乎已经被广泛看作是不好的做法。然而,Resig的评论仅适用于库/框架代码,即将由其他[特定领域的]应用程序/网站使用的代码。
我认为特征检测无疑是库/框架的最佳选择。然而对于特定领域的应用程序来说,我并不确定浏览器检测是否那么糟糕。它适合用于解决难以进行特征检测的已知浏览器特性或者解决浏览器实现该特性时存在的错误。以下是适用浏览器检测的情况:
  • 未跨浏览器的站点/应用程序需要向该客户端浏览器显示警告/对话框/不同页面。这在传统应用程序中很常见。
  • 银行或私人网站严格遵守支持哪些浏览器和版本的策略(以避免已知的安全漏洞可能会损害用户数据)。
  • 微观优化:偶尔会发现某个浏览器在以某种特定方式执行某些操作时比其他浏览器快得多。根据你的用户群体,这可能是一个有利的分支选择。
  • IE6中的PNG透明度不足
  • 许多显示/渲染问题(即:IE CSS支持)仅在特定的浏览器版本中出现,而实际上您并不知道要测试哪个特性。
话虽如此,在进行浏览器检测时,有一些主要的陷阱需要避免(可能由我们大多数人犯过)。

“在 Resig 几年前发表这篇文章之后,我认为浏览器检测已经被广泛地谴责了。” 浏览器检测早在那篇文章之前就是一种不好的做法。我不认为您使用浏览器检测的任何理由都是可行的。在什么内部应用程序中缺乏对 PNG 透明度的支持会成为一个绊脚石呢?编写跨浏览器站点现在比以往任何时候都更加简单,只要对较新的功能采取实用主义方法,例如,您真的会因为某个浏览器不支持 const 或 let 就放弃对其的支持吗?” - RobG
1
@RobG:我从未说过“浏览器检测”等同于“拒绝访问”或“停止支持”。通过浏览器检测,我只是指代码中存在 if (navigator.userAgent...)。如果检测到特定的浏览器,会发生什么取决于具体情况。它可能只意味着使用 gif 而不是 png。 - Crescent Fresh

25

这篇文章很好地解释了如何使用特性检测来替代浏览器嗅探。

事实上,浏览器嗅探的方法非常脆弱。它从理论上来说就很脆弱,因为它依赖于一个任意的userAgent字符串,然后将该字符串实际映射到某种行为。它在实践中也很脆弱,因为时间已经证明了这一点。测试几十个浏览器的每个主要和次要版本并尝试解析其中一些版本的构建号根本不切实际;另一方面,测试某些奇怪行为则更加鲁棒。例如,特性检测通常会捕捉到浏览器供应商无意中从彼此那里复制的错误和不一致之处。

从我的经验来看,在修复IE8中的Prototype.js时,我知道如果我们一开始没有进行嗅探,90%的问题都可以避免。

在修复Prototype.js的过程中,我发现一些需要测试的功能实际上在JS库中非常常见,因此我制作了一个小型的常见特性测试集,供任何想要摆脱嗅探的人使用。


5
理想的解决方案是结合特征检测和浏览器检测两者的优点。前者由于您提到的一些点而变得不可靠,后者则因为有时浏览器发布虚假信息以“使事情正常工作”而可能出现问题。
Mozilla有一个很好的浏览器检测指南,对您也可能有所帮助。
来自维基百科的一段话: “在其历史的各个时期,Web的使用都被某个浏览器主导,以至于许多网站只设计为与特定的浏览器配合使用,而不是按照如W3C和IETF等机构的标准进行设计。这样的网站通常包含“浏览器嗅探”代码,根据接收到的User-Agent字符串来改变发送的信息。这意味着较不流行的浏览器可能无法接收到复杂的内容,即使它们可能能够正确处理它,或在极端情况下拒绝所有内容。因此,各种浏览器会伪装或欺骗这个字符串,以便向这种检测代码标识自己为其他东西;通常,浏览器的真实身份稍后会在字符串中包含。”

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接