zoukankan      html  css  js  c++  java
  • 宏观解析jQuery框架源码

      对于jQuery只停留在应用是可悲的,在做项目的过程,jquery源码一度成为了自己开发的瓶颈,利用了近一天的时间对其宏观上进行了彻底的分析,收获颇丰,分享于此——

      在此说明,所研究的jquery框架版本为1.7.2。

      宏观而言,jQuery框架可分为3个步骤——

      1.定义jQuery变量
      2.扩充jQuery变量及jQuery.fn变量(利用jQuery及jQuery.fn命名空间进行方法的填充)
      3.将jQuery置于全局

      其细节如下——

     1 /**
     2  * 1.定义jQuery变量
     3  *  var jQuery = (function () {
     4  *     
     5  *        //定义一个局部变量jQuery
     6  *        var jQuery = function(selector, context) {
     7  *            //这是所有jQuery选择器的开始
     8  *            return new jQuery.fn.init(selector, context, rootjQuery);
     9  *        },
    10  *        
    11  *        //接着定义其他变量,最主要的是对jQuery函数原型的改造
    12  *         //两者皆为指针,并指向同一起始位置,但后续对两个对象的扩充,使得两者能够指向的位置域有所不同
    13  *        jQuery.fn = jQuery.prototype = {
    14  *            constructor: jQuery,
    15  *            init: function(){...},//定义了所有jQuery选择器的开始
    16  *            //还定义了其他的基础方法,如
    17  *            size: function(){...},
    18  *            toArray: function(){...},
    19  *            get: function(){...},
    20  *            ......
    21  *            port: [].sort,
    22  *            splice: [].splice
    23  *        };
    24  *        
    25  *        //对上面定义的init函数重置原型
    26  *        jQuery.fn.init.prototype = jQuery.fn;
    27  *        
    28  *        //实现了jQuery原型的扩充
    29  *        jQuery.extend = jQuery.fn.extend = function() {
    30  *            ......
    31  *        }
    32  *        
    33  *        //定义完jQuery命名空间下的extend方法,就可以直接扩充jQuery原型了
    34  *        jQuery.extend({
    35  *            noConflict: function(deep){...},
    36  *            //一系列方法...
    37  *        })
    38  *        
    39  *        //鉴别构造器语句...
    40  *        //鉴别浏览器语句...
    41  *        //其他...
    42  *        
    43  *        //要返回这个局部变量jQuery对象,赋值给外围的jQuery变量
    44  *        return jQuery;
    45  *    
    46  *    )();
    47  * 
    48  * 2.扩充jQuery变量及jQuery.fn变量(利用jQuery及jQuery.fn命名空间进行方法的填充)
    49  *     核心的两个方法——
    50  *     jQuery.extend({...})
    51  *     jQuery.fn.extend({...})
    52  * 
    53  * 3.将jQuery置于全局
    54  *     在代码的最后——
    55  *     window.jQuery = window.$ = jQuery;
    56  * 
    57  */

      选取3个例子进行深入研究——

     1 (function ($) {
     2     
     3     /**
     4      * 测试-jquery选择器方法(初始化)、测试-append方法,流程解析如下——
     5      * 1>$('#test', 'body')调用jQuery函数(var jQuery = function(selector, context) {return new jQuery.fn.init(selector, context, rootjQuery);})
     6      *     先对选择器selector(即#test),进行初始化,即(jQuery.fn.init('#test', 'body', [#document]))
     7      *     发现有context(即body),那么要对body进行初始化,再调用$(context).find(selector)方法(即$('body').find('body'))
     8      * 2>对于append方法:会调用jQuery.fn.domManip方法(这个方法会调用jQuery.buildFragment方法),最终会调用selector的dom元素的appendChild方法进行dom操作
     9      */
    10     $('#test', 'body').append('<div class="c2">implant content<div>');    
    11     
    12     /**
    13      * 测试-扩展jQuery对象本身,即,用来在jQuery命名空间上增加新函数
    14      * 看了源码就会发现:
    15      *     它循环了传入的对象参数里面的key-value值,并对jQuery这个函数对象做了扩展,其key值正是传参的key值(min和max)
    16      */
    17     $.extend({
    18         min: function(a, b) { return a < b ? a : b; },
    19         max: function(a, b) { return a > b ? a : b; }
    20     });
    21     $.min(2,3); //2
    22     
    23     /**
    24      * 测试-扩展 jQuery 元素集来提供新的方法(通常用来制作插件)。
    25      * 看了源码就会发现:
    26      *     它与jQuery.extend的调用方法是同一个方法,只不过它对jQuery.fn这个命名空间做了功能扩展
    27      */
    28     $.fn.extend({
    29         check: function() {
    30             return this.each(function() { 
    31                 this.checked = true; 
    32             });
    33         },
    34         uncheck: function() {
    35             return this.each(function() { 
    36                 this.checked = false; 
    37             });
    38         }
    39     });
    40     
    41 /**
    42  * 搜索jQuery变量,只要在这个代码段之前引入jQuery.js框架即可,在这个框架中,会把jQuery变量放置到window对象中
    43  * 源码如下:
    44  *         // Expose jQuery to the global object
    45  *         window.jQuery = window.$ = jQuery;  //这句放在了框架中的最后一句,
    46  *                                             //这句之前,在框架中对jQuery这个局部对象变量(命名空间),做了方法及属性的填充
    47  */
    48 })(jQuery);
    /**
     * 需要的前提知识——
     * 1.JS执行顺序
     *         1>预解析
     *         2>执行
     * 2.函数作用域
     *         1>this(深入理解函数调用模式)
     *         2>变量检索(深入理解变量对象VO)
     *         3>模块模式(深入理解闭包)
     * 3.函数原型继承
     */
    /**
     * 从源码的架构可以学到
     * 1.对于重复利用的变量,提前重新赋值,置为局部变量,这样就减少了变量查找的过程,提高了性能,如:
     *     var document = window.document, 
     *       navigator = window.navigator, 
     *       location = window.location;
     * 2.单变量置顶集中声明
     *     在每一个函数执行域中,把所有该函数所需要的变量在这个函数域的最顶端进行声明,利于变量管理,提高性能,利于维护
     * 3.绝大部分函数定义用的是函数表达式的方式,而非函数声明的方式,这种方式利于代码维护,值得借鉴
     * 4.代码组织方式
     *     1>整体而言,深度利用命名空间的方式管理自己的代码,极大的提高的代码的维护性,值得借鉴
     *     2>利用模块模式,充分划分哪些变量及函数是私有的。利用命名空间的方式,充分划分哪些变量及函数是公有的。
     *     3>功能模块化:并没有一次性将所需要的功能函数扩充于jQuery或jQuery.fn命名空间中,而是充分利用模块化思想进行划分。
     *     4>源码中的每一个函数都是以key-value(这里的value是函数)的形式置于某个命名空间中,而不是简单的功能function的平铺。
     *         增加了代码的维护性,值得借鉴。
     */
    /**
     * 研究jquery框架的作用:
     * 1.在做基于jquery框架的项目时,可依据所需性能合理使用里面的方法,
     *     例如,能完成同样一项功能的两个方法,我们当然要选择性能高的一个方法
     * 2.理解了整体架构,对于细节方法的具体实现,可根据应用具体分析
     * 3.对于以后研究基于jquery的框架(如jquery.validate.js或jquery.ptTimeSelect.js)就不再成为难点
     * 4.记住jquery框架的编码风格,利于对比其他优秀框架,吸取其精华
     */
  • 相关阅读:
    根据数组对象中的某个属性值排序
    vue小知识
    vue项目中config文件中的 index.js 配置
    小问题
    原生无缝轮播
    webpack打包提交代码
    echarts
    面试问题
    MySql
    vue-router 跳转原理
  • 原文地址:https://www.cnblogs.com/jinguangguo/p/2748766.html
Copyright © 2011-2022 走看看