zepto源码解析

比特云影
• 阅读 2118

为什么要看zepto源码

js相当于造房子的砖头,而Vue,react...则是人家造好了的轮子。在工作中一直用的是人家造好的轮子,大家都知道的是前端中轮子变化是很快的,但js是‘不会变的’。所以只有自己会造轮子了才能在前端这条道路上走得更远。并且,个人觉得读完源码后:真正留在自己脑子里的,是框架的设计思想。总之,一直觉得js和设计思想在前端中是最最最最重要的。

需要先了解一下原型和原型链的相关知识

1.每个函数都有一个prototype属性,无论是自定义的还是系统内置的
2.所以通过函数new出来的东西,这个东西都有一个__proto__指向这个函数的prototype
3.当你想要使用一个对象(或一个数组)的某个功能时:如果该对象本身具有这个功能,则直接使用,如果没有就去__proto__中找

怎么读zepto源码

解读zepto的设计

zepto源码解析
上面这张图解析:arr具有push属性,因此可以直接使用。但是arr不具备lzzhyAddName属性,因此需要通过arr._proto = {lzzhyAddName: function(){console.log('my name is lzzhy')}}来添加这个属性后才能用。

流程图解析:
zepto源码解析

PS:源码在设计的时候并不像上面代码那样简单只不过原理是一样的,源码具体实现方式还是得边读边理解。

zepto源码结构

第一步,先整个悦读源码,从大到小以宏观看微观的想法。因此,先将整个大体的结构弄懂:

总结来说,整个结构可以简单抽离成这样:

var zepto = (function(){
    var $, zepto = {}

    // ...省略N行代码

    $ = function(selector,context) {
        return zepto.init(selector,context)
    }

    // ...省略N行代码

    return $
})()
window.zepto = zepto
window.$ === undefined && (window.$ = zepto)

在这里我们可以看到:平常我们$('p')使用zepto的时候,最终会顺藤摸瓜到 $ = function(selector,context) {}这个函数中(其中内容在这一步可不深究),而p选择器也会传递给selector参数。因此经过剥离之后,我们发现下一步需要探究的是$ = function(selector,context) {return zepto.init(selector,context)} 这个函数return出来的zepto.init函数

zepto.init函数

在上一步“zepto源码结构”中我们已经剖析到zepto.init函数了。

函数如下:

zepto源码解析

我们可以看到zepto.init函数大约有几十行,把中间那if...else...操作去掉(其中大致分为四种情况),剩下的就是:

zepto.init = function(selector, context) {
    var dom

    // ...此处省略N行...

    // 分情况对dom赋值:
    // 1.selector为空
    // 2.selector是字符串,其中又分好几种情况
    // 3.selector是函数
    // 4.其他情况,如selector是数组、对象等

    return zepto.Z(dom,elector)
}

在这个函数中,if...else...判断之后,最终 return到zepto.Z函数

zepto.Z函数

在上一步“zepto.init函数”中我们已经剖析到zepto.Z函数了。

zepto源码解析

其中dom指的是数组,$.fn指的是一个包含很多属性的一个对象{......}
371行:把数组或者空数组赋值给 dom
372行:把$.fn赋值给dom._proto隐私原型
373行:把字符串或者空字符串赋值给 dom.selector

下图是$.fn函数部分截图:
zepto源码解析

  • 其中774-779行相对应的':'后的可以转换(如:emptyArray.forEach相当于[].forEach又相当于Array.prototype.forEach);
  • 其中map,slice,ready...函数都是重新定义的,也就是官方文档中我们用到的那些对象函数API如:

zepto源码解析

总结

以上整个分析过程是从大到小将一个个函数分割出来,其中解读了比较重要的几个函数。

源码分析到这里了,那么就用一个简单的代码结构对之前的做个总结。并且根据这个结构,将zepto的初始对象的过程在捋一捋。

var zepto = (function(){
    var $, zepto = {}

    // ...省略N行代码

    zepto.Z = function(dom,selector){
        dom = dom || []
        dom._proto = $.fn
        dom.selector = selector || ''
        return dom
    }
    $ = function(selector,context) {
        return zepto.init(selector,context)
    }

    // ...省略N行代码

    zepto.init = function(selector, context) {
        var dom 

        // ...针对不同情况分别赋值

        return zepto.Z(dom,elector)
    }

    $.fn = {
        // 里面N个重新定义的zepto的API
    }
    return $
})()
window.zepto = zepto
window.$ === undefined && (window.$ = zepto)

zepto源码解析

大致就是这张图的流程,最后的dom是挂载在$.fn上。dom._proto = $.fn

更多请参考我的博客

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Chase620 Chase620
4年前
几个常用js库,别再重复造轮子了
年底了,总结下今年用到的一些有意思的《js轮子》(只是大概列出些比较有意思的库,每个标题都是超链接,可点击自行查阅)希望能对您有用!如有意思的轮子可以在评论列出一起讨论下color(https://links.jianshu.com/go?tohttps%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fco
Karen110 Karen110
4年前
尤大都说了,别用parcel了。但我还是整出了一款Vue3项目搭建工具parcel-vue-app
先放图弱弱的说一句,我真的错了。不该用parcel前几天,尤大开直播说了造轮子的好处,主要还是锻炼自己。所以自己还是义无反顾地把这个项目搭建工具慢慢地造起来。这次升级这次版本是v1.0.5。我们来看下这次版本的预装依赖,我们的项目UI框架预先安装上了antdesignvue@2.1.4,默认是按需加载。为什么这次是引入它,而不是elementplus,主要是
梦想橡皮擦 梦想橡皮擦
4年前
11. 用别人写好的代码,完成我的工作,剩下的时间去摸鱼
今天是持续写作的第<fontcolor"red"11</font/100天。如果你有想要交流的想法、技术,欢迎在评论区留言。Python为何那么多人都喜欢,就是因为很多大佬给我们造好了“轮子”了,拿着大佬的轮子,我骄傲十一、Python模块的设计与应用模块是一个概念,它包含1N个文件,如果文件是Python代码
Wesley13 Wesley13
3年前
Java使用Netty实现简单的RPC
造一个轮子,实现RPC调用在写了一个Netty实现通信的简单例子后,萌发了自己实现RPC调用的想法,于是就开始进行了NettyRpc的工作,实现了一个简单的RPC调用工程。如果也有兴趣动手造轮子的同学,可以先看看之前写的使用Java实现Netty通信(https://www.oschina.net/acti
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Redkale 技术详解 03
Convert(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fredkale.org%2Fconvert.html)是个重复造轮子的组件,却是个飞速的轮子。Redkale之所以重复造轮子主要追求性能和需要与网络数据的序列化很好的结合(Convert与ByteBuffer的结合(ht
Stella981 Stella981
3年前
MPush开源消息推送系统:简洁、安全、支持集群
引言由于之前自己团队需要一个消息推送系统来替换JPUSH,一直找了很久基本没有真正可用的开源系统所有就直接造了个轮子,造轮子的时候就奔着开源做打算的,只是后来创业项目失败一直没时间整理这一套代码,最近比较闲就拿出来给开源做点贡献。作为Java版的开源推送系统,MPUSH还是有很多不错的设计的,特别是对想自己搭建一套推送系统的团队是
Stella981 Stella981
3年前
Spring 中优雅的获取泛型信息
简介Spring源码是个大宝库,我们能遇到的大部分工具在源码里都能找到,所以笔者开源的mica(https://gitee.com/596392912/mica)完全基于Spring进行基础增强,不重复造轮子。今天我要分享的是在Spring中优雅的获取泛型。获取泛型自己解析我们之前的处理方式,代码来源
Stella981 Stella981
3年前
C语言Linix服务器网络爬虫项目(一)项目初衷和网络爬虫概述
一、项目初衷和爬虫概述1.项目初衷  本人的大学毕设就是linux上用c写的一个爬虫,现在我想把它完善起来,让他像一个企业级别的项目。为了重复发明轮子来学习轮子的原理,我们不使用第三方框架(这里是说的是指通常的linux系统编程教材以外的库和接口0,当初我也是在虚拟机上跑的ubuntuputtyvim来开发)来实现。  然而我们造轮