今天看vue的响应原理,突然被提到shim这个词,翻阅些许资料然后整理出以下这些内容。
在JavaScript的世界里,有两个词经常被提到,shim和polyfill。
首先理解这两个词之前我们先来了解一下JavaScript 的兼容性问题。
举个例子,旧版本的 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) }}
这两种方法看似没什么太大的不同,都能解决跨浏览器的兼容问题。但如果你仔细思考,就会发现,这两种方法代表着两种不同思维方式。后者明显的思想更加先进。
我们来看看这两种做法有什么不同。
- jQuery 没有遵循标准,这带来了一个学习成本的问题,我们需要学习这个函数的使用方法;而后者在使用上和标准 API 没什么不同,不存在学习成本。
- 如果某天我们不需要兼容旧 IE 了,后者只要移除兼容代码就可以了,不用改动代码;而前者显然没有这个优势,需要重构代码。遵循标准的代码在维护性方面明显更好。
- 后者还有个好处是,可以按需加载,只在旧浏览器上加载兼容代码。
- 标准的代码在可移植性方面也更具优势。
我们再来看看 shim 和 polyfill 的概念:
一个shim是一个库,它将一个新的API引入到一个旧的环境中,而且仅靠旧环境中已有的手段实现。
一个polyfill就是一个用在浏览器API上的shim。
我们通常的做法是先检查当前浏览器是否支持某个API,如果不支持的话就加载对应的polyfill,然后新旧浏览器就都可以使用这个API了,术语polyfill来自于一个家装产品Polyfilla。
Polyfilla是一个英国产品,在美国称之为Spackling Paste(译者注:刮墙的,在中国称为腻子)。
记住这一点就行:把旧的浏览器想象成为一面有了裂缝的墙,这些[polyfills]会帮助我们把这面墙的裂缝抹平,还我们一个更好的光滑的墙壁(浏览器)。
Paul Irish发布过一个Polyfills的总结页面“HTML5 Cross Browser Polyfills”.es5-shim是一个shim(而不是polyfill)的例子,它在ECMAScript 3的引擎上实现了ECMAScript 5的新特性,而且在node.js上和在浏览器上有完全相同的表现(译者注:因为它能在node.js上使用,不光是浏览器上,所以它不是polyfill)。
举个栗子,有些旧浏览器不支持Number.isNaN方法,Polyfill就可以是这样的:
if
(!Number.isNaN) {
Number.isNaN =
function
(num) {
return
(num !== num);
}
}