shim 和 polyfill

在前端,有兩個詞常常被說起: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)
    }
}

這兩種方法看似沒什麼太大的不一樣,都能解決跨瀏覽器的兼容問題。但若是你仔細思考,就會發現,這兩種方法表明着兩種不一樣思惟方式。後者明顯的思想更加先進。函數

咱們來看看這兩種作法有什麼不一樣。學習

  1. jQuery 沒有遵循標準,這帶來了一個學習成本的問題,咱們須要學習這個函數的使用方法;然後者在使用上和標準 API 沒什麼不一樣,不存在學習成本。
  2. 若是某天咱們不須要兼容舊 IE 了,後者只要移除兼容代碼就能夠了,不用改動代碼;而前者顯然沒有這個優點,須要重構代碼。遵循標準的代碼在維護性方面明顯更好。
  3. 後者還有個好處是,能夠按需加載,只在舊瀏覽器上加載兼容代碼。
  4. 標準的代碼在可移植性方面也更具優點。

咱們再來看看 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 方案了,沒必要重複造輪子。

相關文章
相關標籤/搜索