• jQuery源码学习1——整体架构篇


    由于jQuery的源码比较复杂,所以我选择从jQuery1.0.0版本开始学习,逐步深入。

    而且本系列文章包含大量的个人观点,纯属本人学习的记录

    jQuery1.0.0只有1800行左右的代码,相对来讲看起来还是比较简单的

    首先,想说一下我对jQuery的理解

    jQuery其实就是一个很大的构造函数

    它为我们提供了很多实例化方法

    当然,由于在js中函数本身就是对象

    因此jQuery也提供了很多的静态方法

    个人认为,这些静态方法更为底层

    今天把jQuery的架构梳理了一下

    其实我们可以将其中的方法抽出来,这样看起来就像是一个大的构造函数

    function jQuery(){}
    jQuery.prototype={
        jquery:    "",
        size:    function(){},
        get:    function(){},
        each:    function(){},
        index:    function(){},
        attr:    function(){},
        css:    function(){},
        text:    function(){},
        wrap:    function(){},
        append:    function(){},
        prepend:function(){},
        before:    function(){},
        after:    function(){},
        end:    function(){},
        find:    function(){},
        clone:    function(){},
        filter:    function(){},
        not:    function(){},
        add:    function(){},
        is:    function(){},
        domManip:function(){},
        pushStack:function(){},
        extend:    function(){},    //*扩展其他实例化对象方法的核心方法
        appendTo:    function(){}, //*通过macros的to 扩展的方法
        prependTo:    function(){}, //*通过macros的to 扩展的方法
        insertBefore:    function(){}, //*通过macros的to 扩展的方法
        insertAfter:    function(){}, //*通过macros的to 扩展的方法
                function(){}, //*通过macros的css扩展的方法
        height:        function(){}, //*通过macros的css扩展的方法
        top:        function(){}, //*通过macros的css扩展的方法
        left:        function(){}, //*通过macros的css扩展的方法
        position:    function(){}, //*通过macros的css扩展的方法
        float:        function(){}, //*通过macros的css扩展的方法
        overflow:    function(){}, //*通过macros的css扩展的方法
        color:        function(){}, //*通过macros的css扩展的方法
        background:    function(){}, //*通过macros的css扩展的方法
        eq:        function(){}, //*通过macros的filter扩展的方法
        lt:        function(){}, //*通过macros的filter扩展的方法
        gt:        function(){}, //*通过macros的filter扩展的方法
        contains:    function(){}, //*通过macros的filter扩展的方法
        val:        function(){}, //*通过macros的attr扩展的方法
        html:        function(){}, //*通过macros的attr扩展的方法
        id:        function(){}, //*通过macros的attr扩展的方法
        title:        function(){}, //*通过macros的attr扩展的方法
        name:        function(){}, //*通过macros的attr扩展的方法
        href:        function(){}, //*通过macros的attr扩展的方法
        src:        function(){}, //*通过macros的attr扩展的方法
        rel:        function(){}, //*通过macros的attr扩展的方法
        parent:        function(){}, //*通过macros的axis扩展的方法
        ancestors:    function(){}, //*通过macros的axis扩展的方法
        parents:    function(){}, //*通过macros的axis扩展的方法
        next:        function(){}, //*通过macros的axis扩展的方法
        prev:        function(){}, //*通过macros的axis扩展的方法
        siblings:    function(){}, //*通过macros的axis扩展的方法
        children:    function(){}, //*通过macros的axis扩展的方法
        removeAttr:    function(){}, //*通过macros的each扩展的方法
        show:        function(){}, //*通过macros的each扩展的方法
        hide:        function(){}, //*通过macros的each扩展的方法
        toggle:        function(){}, //*通过macros的each扩展的方法
        addClass:    function(){}, //*通过macros的each扩展的方法
        removeClass:    function(){}, //*通过macros的each扩展的方法
        toggleClass:    function(){}, //*通过macros的each扩展的方法
        remove:        function(){}, //*通过macros的each扩展的方法
        empty:        function(){}, //*通过macros的each扩展的方法
        bind:        function(){}, //*通过macros的each扩展的方法
        unbind:        function(){}, //*通过macros的each扩展的方法
        trigger:    function(){}, //*通过macros的each扩展的方法
        _toggle:    function(){}, 
        toggle:        function(){},
        hover:        function(){},
        ready:        function(){},
        blur:        function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        focus:        function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        load:        function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        resize:        function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        scroll:        function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        unload:        function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        click:        function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        dbclick:    function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        mousedown:    function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        mouseup:    function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        mousemove:    function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        mouseover:    function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        mouseout:    function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        change:        function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        reset:        function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        select:        function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        submit:        function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        keydown:    function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        keypress:    function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        keyup:        function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        error:        function(){}, //*同时绑定了un解绑定方法和one只触发一次的方法
        //*由于上面已经定义过一个show方法,所以这里通过_show将其存储起来,否则下面的show方法会将其覆盖
        _show:        function(){}, //*动画方法
        show:        function(){},
        _hide:        function(){},
        hide:        function(){},
        slideDown:    function(){},
        slideUp:    function(){},
        slideToggle:    function(){},
        fadeIn:        function(){},
        fadeOut:    function(){},
        fadeTo:        function(){},
        animate:    function(){},
        queue:        function(){},
        loadIfModified:    function(){}, //*ajax方法
        load:        function(){},
        ajaxStart:    function(){},
        ajaxStop:    function(){},
        ajaxComplete:    function(){},
        ajaxError:    function(){},
        ajaxSuccess:    function(){}
    };
    jQuery.extend=    function(){};
    jQuery.init=    function(){};
    jQuery.each=    function(){};
    jQuery.className={};
    jQuery.swap=    function(){};
    jQuery.css=    function(){};
    jQuery.curCSS=    function(){};
    jQuery.clean=    function(){};
    jQuery.expr=    function(){};
    jQuery.token=    function(){};
    jQuery.find=    function(){};
    jQuery.getAll=    function(){};
    jQuery.attr=    function(){};
    jQuery.parse=    [];
    jQuery.filter=    function(){};
    jQuery.trim=    function(){};
    jQuery.parents=    function(){};
    jQuery.sibling=    function(){};
    jQuery.merge=    function(){};
    jQuery.grep=    function(){};
    jQuery.map=    function(){};
    jQuery.event=    {};
    jQuery.browser=    function(){};    //*browser方法要基于变量b b=navigator.userAgent.toLowerCase();
    jQuery.boxModel=function(){};    //*boxModel方法要基于browser方法
    jQuery.macros=    {};        //*由此派生出若干实例化对象的方法
    jQuery.isReady=    false;        //*load模块
    jQuery.readyList=[];
    jQuery.ready=    function(){};
    jQuery.setAuto=    function(){};    //*动画模块
    jQuery.speed=    function(){};
    jQuery.queue=    function(){};
    jQuery.dequeue=    function(){};
    jQuery.fx=    function(){};
    jQuery.get=    function(){};    //*ajax模块
    jQuery.getIfModified=function(){};
    jQuery.getScript=function(){};
    jQuery.post=    function(){};
    jQuery.timeout=    0;
    jQuery.ajaxTimeout=function(){};
    jQuery.lastModifed=function(){};
    jQuery.ajax=    function(){};
    jQuery.active=    0;
    jQuery.httpSuccess=function(){};
    jQuery.httpModified=function(){};
    jQuery.httpData=function(){};
    jQuery.param=    function(){};

    当然这里面省略了很多的细节

    在梳理的过程中,发现了很多的问题,如下:

    1、看到jQuery.macros的时候感觉很晕,后来才发现macros其实是把相关的方法或者属性名放到了一起,在合适的时机去初始化

    例如macros.to下面的appendTo prependTo insertBefore insertAfter这四个方法就是在DOM模块被初始化的

    2、v1.0.0对于避免污染全局空间的做法是用new function(){}形成封闭空间,由于之前本人一直用(function(){xxx})();来处理此类情况

    所以看到new function(){}有些无所适从,后来通过查阅相关资料才发现这种方法其实相当于new Aaa;

    new是js中的一个单目运算符,new后面的方法名的括号是可以省略的,所以完整的写法应该是new function(){}() 其中function(){}就相当于一个函数名

    new function(){}通常用来初始化一些东西,但又没有污染全局对象

    3、梳理到动画模块的时候,看到有_show和show两个方法瞬间石化了,不知道是干啥的,

    经过高手指点才发现,在之前的实例化方法中,已经有一个show方法了,所以在定义第二个show方法的时候先用了一个_show方法将第一个show方法存了起来,

    之所以存期来,是因为第二个show方法中需要调用第一个show方法

    附带一句个人之拙见:jQuery的作者为什么不再起一个别的名字额外定义一个方法呢?非得弄成两个同名的方法,还用一个变量缓冲,搞不明白John Resig是怎么想的

    hide和_hide也是同样的道理

    4、本以为作者在处理两个名字一样的方法时就会通过_xxx来存储,但是例外出现在load,我很惊奇的发现实例化对象中有两个load方法

    这样一来后面的load不就覆盖了前一个load了吗?后来定睛一看才发现后面的这个load方法可以大大方方的覆盖前一个load方法,没有任何关系

    因为后面一个load方法实现了前一个load方法的所有功能,而且还扩展了和ajax相关的新的功能

    但是感觉还是不对劲,既然后面的能实现,为什么前面还写一个load方法,感觉前面的load方法定义的既重复又没用

    不过后来经过仔细分析,发现我又错了,因为第一个load方法是通过如下方法加到jQuery的实例化对象上的:

       var e = ("blur,focus,load,resize,scroll,unload,click,dblclick," +
            "mousedown,mouseup,mousemove,mouseover,mouseout,change,reset,select," + 
            "submit,keydown,keypress,keyup,error").split(",");
    for ( var i = 0; i < e.length; i++ ) new function(){ var o = e[i]; jQuery.fn[o] = function(f){ return f ? this.bind(o, f) : this.trigger(o); }; jQuery.fn["un"+o] = function(f){ return this.unbind(o, f); }; jQuery.fn["one"+o] = function(f){
           .....
    }; };

    也就是说,人家除了绑定load方法之外还绑定了unload和oneload方法,要是按照我当初想的那样来变量e中去掉load的话

    后面ajax模块还得将unload和oneload方法也加上去,那样就更麻烦了

    所以采用了现在前面定义再覆盖的形式

  • 相关阅读:
    全栈项目搭建 ------- express
    全栈项目搭建 ------- mysql
    全栈项目搭建 ------- pm2
    基于mysql+node+vue-ssr+webpack全栈项目搭建
    前端技能2020
    项目线上地址汇总2020
    实现一个脚手架
    下载漏洞
    java学习笔记(13-接口、final、多态)
    java学习笔记(12-继承、抽象类)
  • 原文地址:https://www.cnblogs.com/zhaohuiziwo901/p/4950719.html
Copyright © 2020-2023  润新知