zepto源码分析

改变数组对象的原型

首先我们看一下如下代码,如何给一个数组对象添加其他方法

    var arr = [1,2,3];
    arr.__proto__ = {
        addClass: function  () {
            console.log('this is addClass');
        },
        concat: Array.prototype.concat,
        push: Array.prototype.push
    };

    arr.push(4);    // [1, 2, 3, 4]
    arr.addClass();  // 'addClass'

我们修改了数组arr的隐式原型__proto__,使它拥有了更多方法,更多原型继承可以参考另一篇博文原型继承与应用。zepto的原理也是这样:通过$()选择器返回的类数组对象,将对象的隐式原型修改,使zepto对象具有多种方法可以被我们使用

入口

zepto主要结构如下所示,先使用iife(立即执行函数)返回一个值,然后把这个返回值放在window的Zepto属性中,也就是说Zepto成为了一个全局变量。window.$ === false && expression,这是一个简洁写法,意为第一个表达式为false时返回第二个表达式,也就是执行expression。当$没被定义时将$函数赋值给Zepto。所以我们引用$()的时候,实际上是引用Zepto。

var Zepto = (function(){ 
}()
window.Zepto = Zepto;
window.$ === undefined && (window.$ = Zepto) 

显而易见,IIFE的返回值是一个对象,因为我们经过$()选择元素之后,可以使用一系列方法,如addClass ,find等等。那么这个对象是什么,请看以下代码

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

当我们使用$('#aa')的时候,其实执行的是Zepto('#aa'),也就是IIFE的返回值$(selector, context),也就是zepto.init(selector, context)

init函数

    zepto.init = function(selector, context){
        var dom;
        // 分情况对dom赋值:
        // 1. selector 为空
        // 2. selector 是字符串,其中又分好几种情况
        // 3. selector 是函数
        // 4. 其他情况,例如 selector 是数组、对象等
        return zepto.Z(dom, selector)
    }

主逻辑转移到了zepto.Z函数中

zepto.Z函数

上个版本的Z函数是这样实现的:

    zepto.Z = function(dom, selector){
        //如果dom数组没有取到就初始化为数组
        dom = dom || [];
        //源码核心,dom数组的隐式原型被改变了,fn就是这个原型
        dom.__proto__ = $.fn
        //js中 a||b 是一种赋值方式,当a不为真的时候返回b
        dom.selector = selector || ''
        return dom;
    }

最新版本的Z函数如下:

    function Z(dom, selector){
        var i, len = dom ? dom.length : 0
        //进行一次浅拷贝
        for(i = 0; i< len; i++) this[i] = dom[i]
        this.length = len
        this.selector = selector || ''
    }
    zepto.Z = function(dom, selector){
        return new Z();
    }
    zepto.Z.prototype = Z.prototype = $.fn

这种方法直接改变了构造函数Z的原型,导致new出来的对象的__proto__指向$.fn,和上面的方法效果相同,唯一不同的是,最新的Z函数返回的是像

    {
       0: dom[0],
       1: dom[1],
       2: dom[2],
       length: 3,
       selector: ''
    }

前者的对象称为类数组对象,而原来是数组

    [dom[0], dom[1], dom[2]]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值