Polyfill源码阅读

Polyfill源码阅读

自己作为前端大半年的新手,刚刚红皮书看完,开始看一些比较浅层次的源码,来加深对于规范的理解。看polyfill顺便可以看一下js的兼容,还可以了解一些不常用的API,这里记录了自己一些阅读所得,欢迎大神指教。

CSSOM

getBoundingClientRect这个方法在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这个方法得到这个元素的size并且相对于视图的定位,返回的几个值都是只读

这里对getBoundingClientRect方法在ie8下面没有width和height进行了休整。就是对ie8 window下的TextRectangle进行了defineProperties。将width和height进行了定义(这里的定义之所以使用defineProperties是因为这里定义了访问器属性,这个属性不能直接定义)。注意在新的浏览器里面,TextRectangle已经改名了。

注意这里使用的defineProperties在ie 8以下并不支持,所以这个polyfill已经对这个方法进行了修整。就是循环调用了ie8支持的defineProperty而已,至于ie7以下不支持的defineProperty,会在下面进行分析。


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

这里通过hasOwnProperty这个判断来只遍历properties里面的属性,而不是原型对象上的属性;使用call来调用是为了防止对象上自己申明了这个方法,这样子可以使用原型上的。


var s = {};

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

这里通过Object方法来判断传入的是不是一个object~这个写法有点意思。

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;

};

看的好开心,感觉实现很有意思,通过支持率较好的css选择器来做这件事情

就是新建一个style的元素,并且使用传入的字段作为选择器,然后自定义了一个x-qsa的属性。使用到了expression这个东西来调用js,就是应用到的元素自身推入一个准备好的数组中。

然后遍历数组,得到最后的结果了,大赞!!

写法虽然不错,但是css的expression ie8以后不再支持了,比较尴尬,但是用这个来兼容ie7及以下还是很有意思的。

querySelector

就是调用querySelectorAll,然后返回第一个值就行了

getElementsByClassName

类似的,调用上面的querySelectorAll,只要在前面替换个.就行了

Node 类型

因为ie没有公布它的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;

});

重写了这几个方法之后对window和element应用。

DOMTokenList

这个东西就是一个接口,一个格式,元素的classList,rellist就是遵从的这个规范,就是以空格分开的一些字符串而已。这里就是为IE9以下重写了这个东西,提供了一个构造函数,并且使用defineProperty来提供那些toggle,add等等的方法。

es5

getPrototypeOf

这个方法IE8以下不支持。

实现就是在判断了obj !== Object(obj)也就是返回obj.__proto__ || obj.constructor.prototype || Object.prototype,proto这个属性是一些浏览器自己的实现(google,safari,ff)的,不推荐使用。

注意这个方法在ES6下的shim比较复杂,因为在ES6下,一个字符串会返回String.prototype,而es5则会报错,不过这个方法支持的很好。参见ES6支持

getOwnPropertyNames

IE8以下不支持。

这个就是返回所有属于他自己的属性,实现就是在for in中运行一次Object.prototype.hasOwnProperty就可以了。

这个polyfill有一些问题,不能cover下面的,参见mdn文档规范


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

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

因为他的写法是通过for in循环的,而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;

};

第一个参数是原型,第二个参数是property,才开始还以为这里比mdn文档网站上的polyfill写的好。因为他敢用defineProperties,结果后来才发现他也就支持了get,set和value。

mdn上的直接循环赋值了第二个参数,所以那些getter,setter,writable,enumerable属性没法设定了,这里鸡贼的调用了defineProperties,后面他的实现也只有getter和setter。

这里把constructor赋值回去的做法已经被放弃了,浏览器都已经放弃这一步操作了....

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;

};

}

}());

因为IE8部分支持了这个方法(只支持DOM Object),所以这里的检测调用了一次,并用了个try catch来返回值。

这里在能够使用IE8自带的情况下返回自带的。

然后就是使用了两个已经被废弃的函数。__defineGetter____defineSetter__来操作访问器属性,但是那些enumerable,writable就不行了。

Object.defineProperties

这里就是对传入的properties进行for in,然后用hasOwnProperty检测一下。再调用上面的Object.defineProperty。

先写到这里,顺便给个github的传送门,喜欢的朋友star一下啊,自己平时遇到的问题,以及学习所得在上面都会进行记录~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容

  • 以前对浏览器兼容性问题只是大概知道一些点,没想到这次真正着手去做的时候,还是碰到了很多问题。刚开始的时候一边解决问...
    沮溺阅读 27,758评论 2 11
  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 3,191评论 0 4
  • 普通创建对象和字面量创建对象不足之处:虽然 Object 构造函数或对象字面量都可以用来创建单个对象,但这些方式有...
    believedream阅读 2,340评论 2 18
  • 二十五岁的某一天,有一个初秋的夜晚。 那个鬼使神差的夜晚,你约她相见。 在这之前,你问了她很多问题。 是否证明你想...
    会喝狂药的狼阅读 191评论 0 0
  • 春夏已然碎落 不堪寻找 秋来心爽 收获丰实黄彩 欣然逸致 捡拾记忆碎片 夹入生命的书页 封存心扉 拂去喧哗浮躁 赢...
    梅蕊新说阅读 399评论 6 29