在前端,有兩個詞常常被說起:shim 和 polyfill。最近在翻譯文章時又遇到了 polyfill 這個詞,準備把這兩個概念理清楚。javascript
關於 JavaScript 的兼容性問題,一般有不一樣的解決方案。前端
舉個例子,舊版本的 IE 不支持標準的 XMLHttpRequest,但支持自家的 ActiveXObject 方法,對此有如下兩種解決方案。java
jQuery 的作法是,把兩種方法封裝成 $.ajax
函數。使用時,只要熟悉 $.ajax
方法就能夠了,不用考慮瀏覽器的兼容問題。ajax
// 僞代碼 $.ajax = function(url) { if (isIE) { XMLHttpRequest(url) } else { ActiveXObject(url) } }
還有一種方法是,判斷瀏覽器是否支持 XMLHttpRequest,若是不支持,就用 ActiveXObject 實現一個功能跟 XMLHttpRequest 徹底同樣的函數。瀏覽器
// 僞代碼 if (!XMLHttpRequest) { XMLHttpRequest = function(url) { ActiveXObject(url) } }
這兩種方法看似沒什麼太大的不一樣,都能解決跨瀏覽器的兼容問題。但若是你仔細思考,就會發現,這兩種方法表明着兩種不一樣思惟方式。後者明顯的思想更加先進。函數
咱們來看看這兩種作法有什麼不一樣。學習
咱們再來看看 shim 和 polyfill 的概念。url
shim 是一個庫,它將一個新的 API 引入到一箇舊的環境中,並且僅靠舊環境中已有的手段實現prototype
polyfill 是 shim 的一種,它的 API 是遵循標準的。polyfill 的作法一般是:先檢查瀏覽器是否支持某個標準 API,若是不支持,就使用舊的技術對瀏覽器作兼容處理,這樣就能夠在舊的瀏覽器上使用新的標準 API。翻譯
但在實際狀況下,咱們通常說 shim,會特指它的 API 不是遵循標準的,與 polyfill 對立。
上面介紹的兩種方法,前者是 shim,然後者是 polyfill。polyfill 的設計理念更值得去推崇。
理解了概念後,polyfill 的思想就能指導咱們如何去設計 API。
好比說,舊瀏覽器不支持 ES6 的 Array.prototype.find
方法,咱們想要在項目中使用 Array.prototype.find
,只要 polyfill 就好了,而不是封裝一個新的方法。
// 應該這麼作 if (!Array.prototype.find) { Array.prototype.find = function() { // ... } }
// 而不是這麼作 function arrayFind() { if (Array.prototype.find) { // ... } else { // ... } }
固然,不少新的 API 的兼容性問題,網上已經有成熟的 polyfill 方案了,沒必要重複造輪子。