shim 和 polyfill都用于解决前端开发中的浏览器兼容问题。
传统兼容问题
解决兼容问题时,通常有两种思路:
以旧版本的 IE 不支持标准的 XMLHttpRequest,但支持自家的 ActiveXObject 方法为例说明。使用jQuery实现
方法一
将两种方法封装为$.ajax函数,使用时,只要熟悉 $.ajax 方法就可以了,不用考虑浏览器的兼容问题。
$.ajax = function(url) { if (isIE) {XMLHttpRequest(url) } else {ActiveXObject(url) }}
方法二
判断浏览器是否支持 XMLHttpRequest,如果不支持,就用 ActiveXObject 实现一个功能跟 XMLHttpRequest 完全一样的函数。
if (!XMLHttpRequest) { XMLHttpRequest = function(url) {ActiveXObject(url) }}
这两种方法代表不同的思维方式,前者需要学习函数的使用方法,如果不需要兼容时需要重构代码,可维护性差;而后者为标准API,无需学习成本,不使用时只要将代码删除即可,可维护性强,还可以按需加载,只在旧浏览器上加载兼容代码。
所以第二个方法更值得推荐。
shim介绍
Shim 指的是在一个旧的环境中模拟出一个新 API ,而且仅靠旧环境中已有的手段实现,以便所有的浏览器具有相同的行为。主要特征:
- 该 API 存在于现代浏览器中;
- 浏览器有各自的 API 或 可通过别的 API 实现;
- API 的所有方法都被重新实现;
- 拦截 API 调用,并提供自己的实现;
- 是一个优雅降级。
shim 是将不同 api 封装成一种,就比如 jQuery 的 $.ajax 封装了 XMLHttpRequest 和 IE 用 ActiveXObject 方式创建 xhr 对象;
polyfill介绍
polyfill 是一段代码(或者插件),提供了那些开发者们希望浏览器原生提供支持的功能。程序库先检查浏览器是否支持某个API,如果不支持则加载对应的 polyfill。主要特征:
- 是一个浏览器 API 的 Shim;
- 与浏览器有关;
- 没有提供新的API,只是在 API 中实现缺少的功能;
- 以只需要引入 polyfill ,它会静静地工作;
而polyfill 特指 shim 成的 api 是遵循标准的,其典型做法是在IE浏览器中增加 window.XMLHttpRequest ,内部实现使用 ActiveXObject。
区别
shim一般指一些做兼容性的库,用来弥补旧浏览器对新特性支持的不足。都会预先加载,强调新旧浏览器使用同一套代码。
pollfill也会对浏览器的不足做补充,但一般都会用语句来判断此浏览器是否支持此特性,然后通过动态引入script标签的方法来加载。
shim 的概念要比 polyfill 更大一些,可以将 polyfill 理解为专门兼容浏览器 API 的 shim 。简单的说,如果浏览器X支持标准规定的功能,那么 polyfill 可以让浏览器 Y 的行为与浏览器 X 一样。