Polyfill源碼閱讀

Polyfill源碼閱讀

自己作為前端大半年的新手,剛剛紅皮書看完,開始看一些比較淺層次的源碼,來加深對(duì)于規(guī)范的理解。看polyfill順便可以看一下js的兼容,還可以了解一些不常用的API,這里記錄了自己一些閱讀所得,歡迎大神指教。

CSSOM

getBoundingClientRect這個(gè)方法在ie8下的修正


if ('TextRectangle' in this && !('width' in TextRectangle.prototype)) {

Object.defineProperties(TextRectangle.prototype, {

'width': { get: function() { return this.right - this.left; } },

'height': { get: function() { return this.bottom - this.top; } }

});

}

getBoundingClientRect這個(gè)方法得到這個(gè)元素的size并且相對(duì)于視圖的定位,返回的幾個(gè)值都是只讀

這里對(duì)getBoundingClientRect方法在ie8下面沒有width和height進(jìn)行了休整。就是對(duì)ie8 window下的TextRectangle進(jìn)行了defineProperties。將width和height進(jìn)行了定義(這里的定義之所以使用defineProperties是因?yàn)檫@里定義了訪問器屬性,這個(gè)屬性不能直接定義)。注意在新的瀏覽器里面,TextRectangle已經(jīng)改名了。

注意這里使用的defineProperties在ie 8以下并不支持,所以這個(gè)polyfill已經(jīng)對(duì)這個(gè)方法進(jìn)行了修整。就是循環(huán)調(diào)用了ie8支持的defineProperty而已,至于ie7以下不支持的defineProperty,會(huì)在下面進(jìn)行分析。


Object.prototype.hasOwnProperty.call(properties, name)

這里通過hasOwnProperty這個(gè)判斷來只遍歷properties里面的屬性,而不是原型對(duì)象上的屬性;使用call來調(diào)用是為了防止對(duì)象上自己申明了這個(gè)方法,這樣子可以使用原型上的。


var s = {};

s === Object({}) //true

這里通過Object方法來判斷傳入的是不是一個(gè)object~這個(gè)寫法有點(diǎn)意思。

Dom

querySelectorAll


document.querySelectorAll = function(selectors) {

var style = document.createElement('style'), elements = [], element;

document.documentElement.firstChild.appendChild(style);

document._qsa = [];

style.styleSheet.cssText = selectors + '{x-qsa:expression(document._qsa && document._qsa.push(this))}';

window.scrollBy(0, 0);

style.parentNode.removeChild(style);

while (document._qsa.length) {

element = document._qsa.shift();

element.style.removeAttribute('x-qsa');

elements.push(element);

}

document._qsa = null;

return elements;

};

看的好開心,感覺實(shí)現(xiàn)很有意思,通過支持率較好的css選擇器來做這件事情

就是新建一個(gè)style的元素,并且使用傳入的字段作為選擇器,然后自定義了一個(gè)x-qsa的屬性。使用到了expression這個(gè)東西來調(diào)用js,就是應(yīng)用到的元素自身推入一個(gè)準(zhǔn)備好的數(shù)組中。

然后遍歷數(shù)組,得到最后的結(jié)果了,大贊?。?/p>

寫法雖然不錯(cuò),但是css的expression ie8以后不再支持了,比較尷尬,但是用這個(gè)來兼容ie7及以下還是很有意思的。

querySelector

就是調(diào)用querySelectorAll,然后返回第一個(gè)值就行了

getElementsByClassName

類似的,調(diào)用上面的querySelectorAll,只要在前面替換個(gè).就行了

Node 類型

因?yàn)閕e沒有公布它的Node Type。所以這里添加了Node.ELEMENT_NODE這些。

DOMException

與上面類似的,定義了DOMException的一些種類

Event

重寫了ie8以下的一些事件處理,包括通過attachevent來模擬addEventListener,通過detachEvent來模擬removeEventListener,這些ie9才支持


[Window, HTMLDocument, Element].forEach(function(o) {

o.prototype.addEventListener = addEventListener;

o.prototype.removeEventListener = removeEventListener;

});

重寫了這幾個(gè)方法之后對(duì)window和element應(yīng)用。

DOMTokenList

這個(gè)東西就是一個(gè)接口,一個(gè)格式,元素的classList,rellist就是遵從的這個(gè)規(guī)范,就是以空格分開的一些字符串而已。這里就是為IE9以下重寫了這個(gè)東西,提供了一個(gè)構(gòu)造函數(shù),并且使用defineProperty來提供那些toggle,add等等的方法。

es5

getPrototypeOf

這個(gè)方法IE8以下不支持。

實(shí)現(xiàn)就是在判斷了obj !== Object(obj)也就是返回obj.__proto__ || obj.constructor.prototype || Object.prototype,proto這個(gè)屬性是一些瀏覽器自己的實(shí)現(xiàn)(google,safari,ff)的,不推薦使用。

注意這個(gè)方法在ES6下的shim比較復(fù)雜,因?yàn)樵贓S6下,一個(gè)字符串會(huì)返回String.prototype,而es5則會(huì)報(bào)錯(cuò),不過這個(gè)方法支持的很好。參見ES6支持

getOwnPropertyNames

IE8以下不支持。

這個(gè)就是返回所有屬于他自己的屬性,實(shí)現(xiàn)就是在for in中運(yùn)行一次Object.prototype.hasOwnProperty就可以了。

這個(gè)polyfill有一些問題,不能cover下面的,參見mdn文檔規(guī)范


var arr = ['a', 'b', 'c'];

console.log(Object.getOwnPropertyNames(arr).sort()); // logs '0,1,2,length'

因?yàn)樗膶懛ㄊ峭ㄟ^for in循環(huán)的,而length在array中是不可枚舉的,作者表示除了原生的getOwnPropertyNames,其他沒法拿到不可枚舉的。

Object.create


Object.create = function (prototype, properties) {

if (typeof prototype !== "object") { throw TypeError(); }

function Ctor() {}

Ctor.prototype = prototype;

var o = new Ctor();

if (prototype) { o.constructor = Ctor; }

if (properties !== undefined) {

if (properties !== Object(properties)) { throw TypeError(); }

Object.defineProperties(o, properties);

}

return o;

};

第一個(gè)參數(shù)是原型,第二個(gè)參數(shù)是property,才開始還以為這里比mdn文檔網(wǎng)站上的polyfill寫的好。因?yàn)樗矣胐efineProperties,結(jié)果后來才發(fā)現(xiàn)他也就支持了get,set和value。

mdn上的直接循環(huán)賦值了第二個(gè)參數(shù),所以那些getter,setter,writable,enumerable屬性沒法設(shè)定了,這里雞賊的調(diào)用了defineProperties,后面他的實(shí)現(xiàn)也只有g(shù)etter和setter。

這里把constructor賦值回去的做法已經(jīng)被放棄了,瀏覽器都已經(jīng)放棄這一步操作了....

Object.defineProperty


(function() {

if (!Object.defineProperty ||

!(function () { try { Object.defineProperty({}, 'x', {}); return true; } catch (e) { return false; } } ())) {

var orig = Object.defineProperty;

Object.defineProperty = function (o, prop, desc) {

// In IE8 try built-in implementation for defining properties on DOM prototypes.

if (orig) { try { return orig(o, prop, desc); } catch (e) {} }

if (o !== Object(o)) { throw TypeError("Object.defineProperty called on non-object"); }

if (Object.prototype.__defineGetter__ && ('get' in desc)) {

Object.prototype.__defineGetter__.call(o, prop, desc.get);

}

if (Object.prototype.__defineSetter__ && ('set' in desc)) {

Object.prototype.__defineSetter__.call(o, prop, desc.set);

}

if ('value' in desc) {

o[prop] = desc.value;

}

return o;

};

}

}());

因?yàn)镮E8部分支持了這個(gè)方法(只支持DOM Object),所以這里的檢測(cè)調(diào)用了一次,并用了個(gè)try catch來返回值。

這里在能夠使用IE8自帶的情況下返回自帶的。

然后就是使用了兩個(gè)已經(jīng)被廢棄的函數(shù)。__defineGetter____defineSetter__來操作訪問器屬性,但是那些enumerable,writable就不行了。

Object.defineProperties

這里就是對(duì)傳入的properties進(jìn)行for in,然后用hasOwnProperty檢測(cè)一下。再調(diào)用上面的Object.defineProperty。

先寫到這里,順便給個(gè)github的傳送門,喜歡的朋友star一下啊,自己平時(shí)遇到的問題,以及學(xué)習(xí)所得在上面都會(huì)進(jìn)行記錄~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 以前對(duì)瀏覽器兼容性問題只是大概知道一些點(diǎn),沒想到這次真正著手去做的時(shí)候,還是碰到了很多問題。剛開始的時(shí)候一邊解決問...
    沮溺閱讀 28,071評(píng)論 2 11
  • 第5章 引用類型(返回首頁(yè)) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,687評(píng)論 0 4
  • 普通創(chuàng)建對(duì)象和字面量創(chuàng)建對(duì)象不足之處:雖然 Object 構(gòu)造函數(shù)或?qū)ο笞置媪慷伎梢杂脕韯?chuàng)建單個(gè)對(duì)象,但這些方式有...
    believedream閱讀 2,588評(píng)論 2 18
  • 二十五歲的某一天,有一個(gè)初秋的夜晚。 那個(gè)鬼使神差的夜晚,你約她相見。 在這之前,你問了她很多問題。 是否證明你想...
    會(huì)喝狂藥的狼閱讀 234評(píng)論 0 0
  • 春夏已然碎落 不堪尋找 秋來心爽 收獲豐實(shí)黃彩 欣然逸致 撿拾記憶碎片 夾入生命的書頁(yè) 封存心扉 拂去喧嘩浮躁 贏...
    梅蕊新說閱讀 514評(píng)論 6 29

友情鏈接更多精彩內(nèi)容