前端就像原始丛林,很多东西等待Web开发人员去探索去开拓。

HTML5的很多功能并不是所有浏览器都支持。为了解决跨浏览器兼容性问题,Introducing HTML5一书的合著者Remy Sharp在该书中首次提到了ployfilling的概念(见图)。

enter image description here

Remy在自己2010年10月8日的博客中专文介绍了这个新词的来源:What is a Polyfill?。这个词其实源英国的一种墙面填料,品牌为Polyfilla,这种填料在美国叫Spackling Paste(Spackle是美国抹墙粉的一个品牌),当然在我们中国一般叫“腻子”或“填泥”(对应的英文单词是putty和filler)。

在文中,Remy解释说With that in mind: think of the browsers as a wall with cracks in it. These polyfillers help smooth out the cracks and give us a nice smooth wall of browsers to work with.(把浏览器想象成有裂缝的墙面,而用腻子可以把这些裂缝填平,最后得到的是光滑的浏览器“墙面”。)

他给出的定义是:

A polyfill, or polyfiller, is a piece of code (or plugin) that provides the technology that you, the developer, expect the browser to provide natively. Flattening the API landscape if you will.(一段代码或插件,可以让开发人员使用应有的技术,就像浏览器原生提供该功能一样。换句话说,它能帮你抹平API之墙。)

Polyfill中的poly,我理解是“多功能”的意思。polyfit-“多项式拟合”。

文中提到Alex Sexton将ployfill归类为一种“回归增强”(Regressive Enhancement)。同时,也提到了Paul的定义:

A shim that mimics a future API providing fallback functionality to older browsers.(一种模仿未来API并为旧浏览器提供后备功能的“衬垫”)

enter image description here

文中提到他在2010年6月ThinkVitamin谈HTML5 Storage APIs时,实验性地提到polyfill这个新词儿(他的其他参会日程)。而最关键的是,他已经在Introducing HTML5中“偷偷地”用了这个词,希望能够得到读者和业界的认同。

结果,在2010年JS Conf上,Paul Irish发表了“一组polyfill和shim”。然后,Polyfill这个词就不胫而走,得到了社区的认同。

Modernizr的文档页面上,也对polyfill给出了定义和详细解释。以下是对Polyfills and Modernizr一节中相关内容的编译:

Modernizr库只能帮你在IE中用上HTML5新的区块元素,但除此之外不会“现代化”(modernize)任何功能(换言之,它只能检测是否存在原生功能,不能提供该功能的实现)。之所以叫Modernizr,目的就是让前端开发以及我们自己现代化、跟上时代步伐。尽管Modernizr不能提供现代化的功能,但有很多脚本可以实现浏览器不支持的功能。一般来说,这些脚本就叫做polyfill。

“polyfill(n):一种JavaScript“衬垫”,用于在旧浏览器中提供标准API。”

因此,websocket polyfill会创建一个window.WebSocket对象,提供与原生实现相同的属性和方法。这意味着你可以使用真正API面向未来开发啦!只要在不支持该API的浏览器中加载兼容性polyfill即可。

好消息是,Modernizr检测的每一个HTML5功能,现在都有了对应的polyfill。没错,绝大多数情况下,即使是在不支持相关HTML5和CSS3功能的浏览器,都可以再现这些功能。是的,不仅现在可以使用HTML5,过去其实也是可以的!

不过,还是要给大家一个大大的警告:不能因为能用polyfill就乱用。最关键的是还是要关注最佳用户体验,换句话说就是——快!在IE7里要加载5个兼容性脚本,然后可以让它跟Chrome和Opera一样,并不是一个明智的选择。没有一成不变的规则,但也不要忘了页面加载的脚本一多,就可能影响到用户体验。而且,请你记住:没有任何人会在两个浏览器中比较你的站点;即使它在不同用户那里的外观和行为不一致,也没有问题。

至于polyfill这个词的中文译法,目前没有找到公认的译法,毕竟是一个新词。在Adobe开发人员社区中,著名图书作者David Powers于2011年8月发表的一篇文章“使用Modernizr 检测HTML5和CSS3浏览器支持功能”中提到了这个词。

在Remy的这篇文章下面,一位开发人员alexander farkas提出问题:

希望能进一步分清什么是polyfill,什么是shim。因为有很多shim好像是实现标准的API,而有很多shim又好像只是在其他一两种技术基础上加了一个抽象层。怎么区分polyfill与shim?

Remy举一个例子,并解释:

如果浏览器X支持标准规定的功能,那么polyfill可以让浏览器Y的行为与浏览器X一样。

比如,jQuery不是polyfill,但下面这段代码是:

// 首先包含jQuery
if (!document.querySelectorAll) {
  Element.prototype.querySelectorAll = function (q) {
    return $(this).find(q).get();
  };

  // document对象不是Element对象的后代,
  // 因此手工重写
  document.querySelectorAll = Element.prototype.querySelectorAll;
}

关于如何开发polyfill,Modernizr给出的polyfill列表中,还推荐了Addy Osmani的一篇文章,2011年8月12日发表:“The Developer's Guide To Writing Cross-Browser JavaScript Polyfills”,值得翻译。

最后还有一个小插曲。有人给Remy留言说,为什么不干脆美国化,把这种脚本称为Spackle?Remy答曰:因为我是英国人,哈哈。