polyfill是什麼?
Polyfill是用在瀏覽器API上的shim。我們通常的做法是先檢查當前瀏覽器是否支持某個API,如果不支持的話就加載對應的polyfill。這樣新舊瀏覽器就都可以使用相同的API了。把舊的瀏覽器想象成爲一面有了裂縫的牆,這些polyfill(膩子)會幫助我們把這面牆的裂縫抹平。
polyfill 是 shim 的一種。一個polyfill可以是一段代碼(或者插件),提供了那些開發者們希望瀏覽器原生就支持的功能。主要撫平不同瀏覽器之間對js實現的差異。
shim是什麼?
shim 是將不同 API 封裝成一種的庫,shim將一個新的API
引入到一箇舊的環境中,而且僅靠舊環境中已有的手段實現。
比如 jQuery是一個shim庫,jQuery 的 $.ajax方法 封裝了 XMLHttpRequest 方法和 IE 用 的ActiveXObject 方式來創建 xhr 對象(通俗地講,依靠瀏覽器原生支持的兩個API,封裝成$.ajax這個新的API,使用時,只需調用$.ajax這個新的API ,而不是調用XMLHttpRequest或ActiveXObject這兩個原生API )。
可以把shim,理解成能夠兼容之前版本的庫,是一種優雅降級。
polyfill 特指 shim 成的 api 是遵循瀏覽器標準的,其典型做法是在IE瀏覽器中增加window.XMLHttpRequest ,內部實現使用 ActiveXObject(見下面舉例)。
如何區分polyfill和shim?
舉例1
問題:舊版本的 IE 不支持標準的 XMLHttpRequest,但支持自家的 ActiveXObject 方法
解決辦法1-shim(jQuery中,把XMLHttpRequest和ActiveXObject這兩個新舊瀏覽器中的原生API,封裝成 $.ajax 這個新的API。使用時,只要熟悉 $.ajax這個新的API 的使用就可以了,不用考慮瀏覽器的兼容問題)
$.ajax = function(url) {
if (isIE) {
XMLHttpRequest(url)
} else {
ActiveXObject(url)
}
}
解決辦法2-polyfill(判斷瀏覽器 是否支持新版瀏覽器中XMLHttpRequest這個原生API,如果不支持,就用舊版瀏覽器中ActiveXObject這個原生API 來實現 一個功能跟 新版瀏覽器中XMLHttpRequest這個原生API 完全一樣的函數,並賦值給XMLHttpRequest這個原生API,這樣,開發者使用時,就還可以使用XMLHttpRequest這個原生API啦,不用再去學習jQuery庫咯)
if (!window.XMLHttpRequest) {
window.XMLHttpRequest = function(url) {
ActiveXObject(url)
}
}
舉例2
問題:舊瀏覽器不支持 ES6 的 Array.prototype.find 方法
解決辦法1-shim(封裝一個新的API,使用時也調用這個新的API)
function arrayFind () {
if (Array.prototype.find) {
// ...
} else {
// ...
}
}
解決辦法2-polyfill(判斷瀏覽器 是否支持新版瀏覽器中Array.prototype.find這個原生API, 如果不支持,就實現一個函數,並賦值給Array.prototype.find這個原生API,這樣,開發者使用時,就還可以使用Array.prototype.find這個原生API啦)
if (!Array.prototype.find) {
Array.prototype.find = function() {
// ...
}
}
總結
以上舉例中,兩種解決辦法都能解決跨瀏覽器兼容的問題,看着也沒有特別的差別。
但是我們更推薦【解決辦法2】,
首先,像shim這樣應用一個新的API,有一定的學習成本,特別是在多人協作的過程中,如果你自己定義了一個方法去解決兼容問題,就需要告知其他開發人員這個新的API應該如何調用。而polyfill的做法,還是調用原生API就OK啦!
其次,polyfill可以實現按需加載,只在舊瀏覽器上加載兼容代碼。
與君共勉:再牛逼的夢想,也抵不住傻逼般的堅持!