垫片和 polyfill 有啥区别?

Posted

技术标签:

【中文标题】垫片和 polyfill 有啥区别?【英文标题】:What is the difference between a shim and a polyfill?垫片和 polyfill 有什么区别? 【发布时间】:2011-09-29 19:11:04 【问题描述】:

两者似乎都用于 Web 开发领域,参见例如html5 Cross Browser Polyfills,上面写着:

所以我们在这里收集了所有的 shims、fallbacks 和 polyfills...

或者,有es5-shim 项目。

在我当前的项目中,我们使用了其中的一些,我想将它们全部放在同一个目录中。那么,这个目录应该叫什么---shims,还是polyfills

【问题讨论】:

reopen:我想“我应该怎么称呼这个目录”可能是基于意见的,但实际上并没有考虑到问题的更大背景——这也不是最重要的方面题。这里的所有答案似乎都是一致的,并且大量使用了事实、参考资料和特定专业知识。 【参考方案1】:

垫片

如果您熟悉适配器模式,那么您就会知道什么是垫片。 Shims 拦截 API 调用并在调用者和目标之间创建一个抽象层。通常,垫片用于向后兼容。例如,es5-shim npm 包可以让你编写 ECMAScript 5 (ES5) 语法,而不用关心浏览器是否运行 ES5。以 Date.now 为例。这是 ES5 中的一个新函数,其中 ES3 中的语法是 new Date().getTime()。如果你使用 es5-shim,你可以编写 Date.now,如果你运行的浏览器支持 ES5,它就会运行。但是,如果浏览器正在运行 ES3 引擎,es5-shim 将拦截对 Date.now 的调用并返回 new Date().getTime() 代替。这种拦截称为匀场。来自 es5-shim 的相关源代码如下所示:

if (!Date.now) 
    Date.now = function now() 
        return new Date().getTime();
    ;

Polyfill

Polyfilling 实际上只是一个专门的 shiming 版本。 Polyfill 是关于在 API 中实现缺失的功能,而 shim 并不一定是关于实现缺失的功能,因为它是关于纠正功能。我知道这些看起来过于模糊,但是当 shims 被用作更广泛的术语时,polyfill 用于描述为旧版浏览器提供向后兼容性的 shims。 因此,虽然 shims 用于掩盖旧罪,但 polyfills 用于及时恢复未来的增强功能。 例如,IE7 中不支持 sessionStorage,但是 sessionstorage npm 包中的 polyfill 将通过使用诸如在窗口的 name 属性中存储数据等技术在 IE7(及更早版本)中添加此功能或使用 cookie。

【讨论】:

因此,虽然 shims 用于掩盖旧罪,但 polyfills 用于及时带来未来的增强功能。 这总结了我的一切.谢谢你的清晰解释。 这个答案很有帮助,谢谢。但在我看来,这两个术语通常在网络上并没有精确使用,包括 es5-shim。根据您的定义,我认为 es5-shim 是 shims 和 polyfills 的混合体。 WOW -> 所以当 shims 用于掩盖旧罪时,polyfills 用于将未来的增强带回过去。 日期示例在我看来就像一个 Polyfill。为什么我认为它是 Polyfill?因为 Date.now 是本机调用。 Polyfill 会将具有相同 API 的功能无缝添加到浏览器。垫片带有一个新的 API,例如:MyShim.Date.now(); 如果我错了,请纠正我。【参考方案2】:

Polyfill 只是一个脚本,它会检查浏览器中某个 API 的存在,好吗? 如果浏览器中不存在该 API,polyfill(这是一个简单的脚本)将执行如下操作:

例如,我将在浏览器中使用蓝牙 API,但我知道某些浏览器没有这样的 API,所以我会写这样的东西来检查我的 API 是否存在:

if(!navigator.bluetooth)  // write polyfill here  

Shim 也是一个脚本,主要作为插件或库提供,它是如何工作的?

实际上,它将覆盖现有的 API 并实现不同的行为,以支持旧浏览器中的新 API。 值得注意的是,Shims 主要用于向后兼容。

【讨论】:

【参考方案3】:

shim 是执行 API 调用拦截并提供抽象层的任何代码。它不一定限于 Web 应用程序或 HTML5/CSS3。

polyfill 是一种 shim 类型,它使用通常使用 javascript 或 Flash 的现代 HTML5/CSS3 功能改进旧版浏览器。

回答您的具体问题,如果您想保持目录通用,请致电您的目录shims

【讨论】:

【参考方案4】:

几年前写的一篇很棒的文章很好地解释了这一点:

What is a Polyfill?

在文章中,(2) 被简单地对比如下:

Shim:您可以添加一段代码(即JavaScript)来修复某些功能,但它通常会有它自己的 API

Polyfill: 可以放入的东西(即JavaScript),它会默默地模仿现有的浏览器API不支持。

【讨论】:

我认为这是对常见用法和 Remy Sharp 在您链接到的博客文章中实际所说的内容的误导性表示。现在,Shim 最常与 polyfill 同义使用(尤其参见 es5-shim 和 es6-shim),Remy 特别喜欢说 对他 “shim”这个词暗示了一个自定义 API(与 shim.gif 相比)。他并没有规定要以这种方式使用这些词,通过说“对我”,他默认他的用法并不普遍。【参考方案5】:

从他的书中引用Axel Rauschmayer Speaking JavaScript

shim 是一个库,它为旧环境带来了新的 API,使用 只是那个环境的手段。 polyfill 是浏览器 API 的填充程序。它通常检查浏览器是否 支持 API。如果没有,polyfill 会安装自己的 执行。这允许您在任何一种情况下都使用 API。这 polyfill 一词来自于家装产品;根据Remy Sharp:

Polyfilla 是一种英国产品,在美国被称为 Spackling Paste。考虑到这一点:将浏览器想象成一堵有裂缝的墙。这些 [polyfills] 帮助抚平裂缝,给我们一个光滑的墙壁 可以使用的浏览器。

【讨论】:

【参考方案6】:

据我了解:

polyfill 是检测某个“预期”API 是否缺失并手动实现它的代码。例如。

if (!Function.prototype.bind)  Function.prototype.bind = ...; 

垫片是拦截现有 API 调用并实现不同行为的代码。这里的想法是在不同的环境中标准化某些 API。因此,如果两个浏览器以不同的方式实现相同的 API,您可以在其中一个浏览器中拦截 API 调用,并使其行为与另一个浏览器保持一致。或者,如果浏览器的某个 API 存在错误,您可以再次拦截对该 API 的调用,然后绕过该错误。

【讨论】:

以上是关于垫片和 polyfill 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

导入 ES6 和 ES7 core-js polyfill 有啥用?

shim和polyfill有什么区别

Polymer 和 Web Components polyfill 之间的区别?

babel的polyfill和runtime的区别

转义babel的polyfill和runtime的区别

JavaScriptPolyfillShim 在JavaScript中Shim和Polyfill有什么区别?