zoukankan      html  css  js  c++  java
  • jQuery 源码分析和使用心得

      core是jQuery的核心内容, 包含了最基础的方法, 比如我们常用的 $(selector, context), 用于遍历操作的 each, map, eq, first 识别变量类型的 isArray, isNumeric, type 等 . 这些方法为jQuery后续操作提供最基础的支持. 

    构造函数 jQuery( selector, context )

      说到jQuery, 大家可能最熟悉的就是 $(selector, context) , 我觉得这也是jQuery受到人们欢迎的很大一部分原因, 因为这个方法非常的强大.

        // Define a local copy of jQuery
        jQuery = function( selector, context ) {
            // The jQuery object is actually just the init constructor 'enhanced'
            // Need init if jQuery is called (just allow error to be thrown if not included)
            return new jQuery.fn.init( selector, context );
        },

      这里我们很明显的看到一个关键词就是new ,这说明每一次调用$()就会new一个jQuery对象出来 , 有些人可能不注意这一点就会写出下面的代码, 或者会出现 $("#id") === $("#id")的这种判断 , 这种写法都是不可取的, 我们应该尽量的节省jQuery的获取次数, 重复利用jQuery对象.

    if($(".class").hasClass()){
        $(".class").removeClass();
    }

    静态属性和原型属性

      从core.js中可以看到两类属性( q君: 函数也是属性哦! ), 一类是以jQuery.extend({})定义的静态属性, 一类是通过  jQuery.fn = jQuery.prototype = {} 进行定义的原型属性. 静态属性是jQuery函数的属性, 通过 $调用, 如$.each . 静态属性通常为与页面元素无关的工具方法. 原型属性是拓展jQuery对象的一些功能, 它持有jQuery对象自身(this) , 为处理自身对象之用 调用形式为  var $a = $("a"); $a.each() .( q君: jQuery里面有两个each ,要分清 )  

      具体的实现方法都比较简单, 就不再一一叙述. jQuery.extend 是一个很常用的方法, 它可以将几个对象合并成一个对象, 并且支持深拷贝和浅拷贝两种方式 , 在做一些默认配置和实现的时候会经常用到.  

    jQuery对象创建

      通过查看 jQuery( selector, context )函数, 知道了 jQuery 调用了 new jQuery.fn.init( selector, context ). 在这句话上面有一条注释: Need init if jQuery is called .  我们在 /src/core/目录下找到init.js. 内容大致如下

    init = jQuery.fn.init = function( selector, context ) {
        //  ...
        //  ...
        return this;
        // ...
        retrun this.constructor( context ).find( selector );
        // ...
        return ( context || rootjQuery ).find( selector );
        // ...
        return typeof rootjQuery.ready !== "undefined" ?
                    rootjQuery.ready( selector ) :
                    // Execute immediately if ready is not present
                    selector( jQuery );
        // ...
        return jQuery.makeArray( selector, this );
        
    }
    
    // Give the init function the jQuery prototype for later instantiation
    init.prototype = jQuery.fn;

      在这个方法里有很多种返回.

        第一种 this, 返回的是init的对象;

        第二种 jquery对象.find(); -> /src/traversing/findFilter.js : find -> return this.pushStack -> return jQuery.merge( this.constructor(), elems ); -> jQuery对象

        第三种 selector(jQuery); 不一定返回jQuery对象

        第四种 rootjQuery.ready( selector ); -> /src/core/ready.js : ready -> return this(rootjQuery) -> jQuery对象

        第五种 jQuery.makeArray( selector, this ); -> var ret = results; return ret; -> jQuery对象

      通过上述观察, 发现jQuery方法只有一种情况下返回的不是jQuery对象: 传入的selector参数为对象, 并且没有加载 /src/core/ready.js 模块. 下面这段代码也会证明这种情况(代码会在附件中, 请及时更新). 

    <!DOCTYPE html>
    <html>
    
        <head>
            <meta charset="utf-8">
            <title>core</title>
        </head>
    
        <body>
            <script src="require.js" data-main="main" type="text/javascript" charset="utf-8"></script>
            <script type="text/javascript" charset="utf-8">
                require(['../src/core/init'], function(init) {
                    var ret = new init(function() {
                        return {
                            name: "not jquery"
                        };
                    });
                    console.log(ret);
                })
            </script>
        </body>
    
    </html>

      再来看第一种情况, return this返回的是init对象, 并不是jQuery对象, 但是我们在下面看到 init.prototype = jQuery.fn; 所以通过init创建的对象也就是jQuery对象. 

    jQuery实现伪数组

      我们在用jQuery的过程中很多情况下会把jQuery当做数组去用. 但是我们从上面创建过程来看, jQuery貌似跟数组并没有什么关系. 那么我们来分析一下他的原型看看为什么jQuery可以像数组一样使用. 

      在这之前我先介绍一下"鸭子类型(duck typing)" ( q君: 鸭子? 好吃吗? ), 什么是鸭子类型? “当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。” 这是一个非常恰当的描述, 在动态语言中我们不需要管一个对象到底是什么类型, 只要他能执行某个方法, 那么我就可以认为他就是某个类型的对象. 

      Javascript就是这样的一种语言. 要实现数组不一定要继承或者使用Array对象. 只要实现了Array对象里面的方法, 就可以认为他是数组. 这里我也发现一个很有趣的事情. 用chrome浏览器进行调试的时候, 我们用console.log输出普通对象和数组的时候输出的格式不一样. 输出对象类似于 " f {length: 0} " , 输出数组类似于 " [1] ". 我们通过下面几行代码做个试验

    var f = function(){this.length = 1; this[0] = "a" }
    console.log(new f());   //  f {0: "a", length: 1}
    var f = function(){this.length = 1;this.splice = function(){};this[0] = "a" }
    console.log(new f());   //  ["a"]

      哈, 多么神奇! chrome把他当成数组了! 如果一个对象中length为数字, splice为方法, 这个对象就会被chrome认为是数组. 大家感兴趣的话可以试一下其他的浏览器. 

      嗯, 我们回过头看jQuery的prototype, jQuery的prototype中包含了数组中常用的 length属性, push , sort , splice , slice等方法. 

      所有jQuery就像一个数组一样使用.

    使用建议

      1. 尽量减少重复使用 $()方法获取相同的对象

      2. $() 大部分会返回jQuery对象, 但不排除在极端情况

      3. jQuery可以当做数组使用, 但不完全是数组, pop, shift 等方法不适用于jQuery对象.

    附件

      http://yunpan.cn/Q7nKEsZ9cqFby  提取码 3a4a

  • 相关阅读:
    Javajdbc
    Web Project添加Struts2框架
    CSS去除免费虚拟主机的广告心得分享
    List<T>采用delegate快速实现排序、查找等操作
    ASP.NET视频采集站核心技术分析(附送对付搜索引擎蜘蛛的贱招)
    Azure完整实例:在线日程表
    [发布]ClouderaCMS: 基于Windows Azure的开源CMS
    获取配置文件节点的值
    asp.net DataGrid排序
    checkbox 获取选中的值
  • 原文地址:https://www.cnblogs.com/chris-hus/p/jquery-analysis-core.html
Copyright © 2011-2022 走看看