虽然最近工做中没有怎么用 zepto ,可是听说 zepto 的源码比较简单,并且网上的资料也比较多,因此我就挑了 zepto 下手,但愿能为之后阅读其余框架的源码打下基础吧。javascript
读Zepto源码系列文章已经放到了github上,欢迎star: reading-zeptohtml
本文阅读的源码为 zepto1.2.0java
阅读zepto以前须要了解 javascript 原型链和闭包的知识,推荐阅读王福朋的这篇文章:深刻理解 Javascript 原型和闭包,写得很详细,也很是易于阅读。git
var Zepto = (function () { ... })() window.Zepto = Zepto window.$ === undefined && (window.$ = Zepto)
若是在编辑器中将 zepto 的源码折叠起来,看到的就跟上面的代码同样。github
zepto 的核心是一个闭包,加载完毕后当即执行。而后暴露给全局变量 zepto
,若是 $
没有定义,也将 $
赋值为 zepto
。segmentfault
在这部分中,咱们先不关注 zepto 的具体实现,只看核心的结构,所以我将zepto中的逻辑先移除,得出以下的核心结构:微信
var zepto = {}, $ function Z(doms) { var len = doms.length for (var i = 0; i < len; i++) { this[i] = doms[i] } this.length = doms.length } zepto.Z = function(doms) { return new Z(doms) } zepto.init = function(doms) { var doms = ['domObj1','domObj2','domObj3'] return zepto.Z(doms) } $ = function() { return zepto.init() } $.fn = { constructor: zepto.Z, method: function() { return this } } zepto.Z.prototype = Z.prototype = $.fn return $
在源码中,能够看出, $
实际上是一个函数,同时在 $
身上又挂了不少属性和方法(这里体如今 $.fn
身上,其余的会在后续的文章中谈到)。闭包
咱们在使用 zepto 的时候,会用 $
去获取 dom
,而且在这些 dom
对象身上都有 zepto 定义的各类各样的操做方法。框架
从上面的伪代码中,能够看到,$
其实调用了 zepto.init()
方法,在 init
方法中,会获取到 dom
元素集合,而后将集合交由 zepto.Z()
方法处理,而 zepto.Z
方法返回的是函数 Z
的一个实例。dom
函数 Z
会将 doms
展开,变成实例的属性,key
为对应 domObj
的索引, 而且设置实例的 length
属性。
读到这里,你可能会有点疑惑,$
最终返回的是 Z
函数的实例,可是 Z
函数明明没有 dom
的操做方法啊,这些操做方法都定义在 $.fn
身上,为何 $
能够调用这些方法呢?
其实关键在于这句代码 Z.prototype = $.fn
,这句代码将 Z
的 prototype
指向 $.fn
,这样,Z
的实例就继承了 $.fn
的方法。
既然这样就已经让 Z
的实例继承了 $.fn
的方法,那 zepto.Z.prototype = $.fn
又是为何呢?
若是咱们再看源码,会发现有这样的一个方法:
zepto.isZ = function(object) { return object instanceof zepto.Z }
这个方法是用来判读一个对象是否为 zepto 对象,这是经过判断这个对象是否为 zepto.Z
的实例来完成的,所以须要将 zepto.Z
和 Z
的 prototype
指向同一个对象。 isZ
方法会在 init
中用到,后面也会介绍。
最后,全部文章都会同步发送到微信公众号上,欢迎关注,欢迎提意见: