zepto源码解析

为什么要看zepto源码

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

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

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

怎么读zepto源码

解读zepto的设计

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

流程图解析:

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.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函数了。

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

下图是$.fn函数部分截图:

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

总结

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

源码分析到这里了,那么就用一个简单的代码结构对之前的做个总结。并且根据这个结构,将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)

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

更多请参考我的博客

原文链接:segmentfault.com

上一篇:xolvio-ddp
下一篇:xolvio-fiber-utils

相关推荐

  • 🔥手写大厂前端知识点源码系列(上)

    如今前端攻城狮的要求越来越高,会使用常见的API已经不能满足现如今前端日益快速发展的脚步。现在大厂基本都会要求面试者手写前端常见API的原理,以此来证明你对该知识点的理解程度。

    4 个月前
  • 🔥前端面试大厂手写源码系列(上)

    如今前端攻城狮的要求越来越高,会使用常见的API已经不能满足现如今前端日益快速发展的脚步。现在大厂基本都会要求面试者手写前端常见API的原理,以此来证明你对该知识点的理解程度。

    3 个月前
  • 🔥 Promise|async|Generator 实现&原理大解析 | 9k字

    笔者刚接触async/await时,就被其暂停执行的特性吸引了,心想在没有原生API支持的情况下,await居然能挂起当前方法,实现暂停执行,我感到十分好奇。好奇心驱使我一层一层剥开有关JS异步编程的...

    4 个月前
  • (源码分析)为什么 Vue 中 template 有且只能一个 root ?

    引言 今年,疫情并没有影响到各种面经的正常出现,可谓是络绎不绝(学不动...)。然后,在前段时间也看到一个这样的关于 Vue 的问题,为什么每个组件 template 中有且只能一个 root? 可能...

    3 个月前
  • 高级选择器解析

    高级选择器解析 一、什么是伪类? 注意!:状态类写法分两种,比如 li:hover 表示选择li本体,li:hover>a表示选择li下面的a元素,状态类选择器只能向下或者向兄弟元素,...

    1 个月前
  • 页面跳转时,点击上报丢失问题解析

    背景 最近在工作中,遇到了页面跳转时点击上报丢失的问题,突出表现在微信ios的webview上,上报后直接跳转的失败率达到了惊人的93%。喝口水压压惊,开始逐步分析问题的发生。

    2 年前
  • 面试题|手写JSON解析器

    这周的 Cassidoo 的每周简讯有这么一个面试题:: 写一个函数,这个函数接收一个正确的 JSON 字符串并将其转化为一个对象(或字典,映射等,这取决于你选择的语言)。

    5 个月前
  • 面试还问redux?那我从头手撸源码吧(中间件篇)

    昨天的文章手写了一版redux的核心源码(https://segmentfault.com/a/1190000016799698),redux库除了数据的状态管理还有一块重要的内容那就是中间件,今天我...

    2 年前
  • 防抖与节流(源码学习)

    最近自己撸了一个轮播图,在点击切换的时候,为了寻求更好的用户体验,引入了节流,在此记录对源码的学习过程 源码来源:underscore(https://github.com/jashkenas/und...

    2 年前
  • 阅读redux源码_compose

    先上源码: 重点看一句就够了: 现在我们先假设一个数组,有3个函数,分别是x,y,z 那么发生什么了,接下来就一步一步解释 1. 变成reduce模式: 2. reduce第一次执行,...

    2 年前

官方社区

扫码加入 JavaScript 社区