先来了解几个jQuery方法:

<li></li>

<li></li>

<li></li>

$("li")  ->  this  ->  jQuery对象  ->    {  0 : "li", 1 : "li", 2 : "li", length : 3  }

$("<li>aaa")  的效果跟   $("<li>")的效果是一样的。

然后来看一下init方法,也就是新建jQuery对象调用的方法:

jQuery.fn = jQuery.prototype = {

  jquery: core_version,        //jQuery的版本

  constructor:jQuery,          //修正constructor的指向,不写这个的话,constructor会指向Object,因为你重写了JQuery的prototype。

   //新建一个构造函数时,会自动在构造函数的prototype对象中新添constructor属性(指向构造函数)。但是为了防止原型对象的覆盖,比如:Person.prototype = {};这时里面的constructor指向会出问题,需要修正,Person.prototype = { constructor: Person}

  init:function(selector,context,rootjQuery){

    var match,elem;

    if(!selector){             //处理这种情况:$(""), $(null), $(undefined), $(false)

      return this;

    }

    if ( typeof selector === "string" ) {
      if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
        // $("<li>")  ->   match = [ null, "<li>", null ];

        // $("<li>1</li><li>2</li>")  ->   match = [ null, "<li>1</li><li>2</li>", null ];
        match = [ null, selector, null ];

      } else {

        //    此正则rquickExpr匹配后,会出现以下几种情况:

        //  1. match = null;           $(".box"), $("div"), $("#div1 div.box")

        //  2. match = ["#div1",null,"div1"];    $("#div1")

        //  3. match = ["<li>aaa","<li>",null];  $("<li>aaa")     

        match = rquickExpr.exec( selector );
      }

      // $("#div1")通过id匹配元素,是在document中执行,不会传入context,所以context为空,因此进入if语句
      if ( match && (match[1] || !context) ) {

        if ( match[1] ) {   // $("<li>"), $("<li>aaa"),$("<li>1</li><li>2</li>")

          //context就是document,因为创建元素只能在document中执行。但是页面里面有iframe时,iframe中的document与页面的document不同,所以$("<li>",document)有第二个参数。一般用不上。
          context = context instanceof jQuery ? context[0] : context;

          //$("<li>",$(document)),得到原生的document。         

          jQuery.merge( this, jQuery.parseHTML(match[1],context && context.nodeType ? context.ownerDocument || context : document,
true
          ) );

          //parseHTML方法:第一个参数传入标签字符串"<li>",第二个参数传入执行上下文document,第三个参数true代表可以新建script标签"<script><\/script>"(script前面的反斜杠需要转义,其他标签不需要),false代表不能。返回值是一个数组:$("<li>") ->   ["li"],  $("<li>1</li><li>2</li>") ->["li","li"]

          //merge方法是把数组转换成jQuery对象:["li"] ->  {0:"li",length:1} ;["li","li"]   ->  {0:"li",1:"li",length:2}

          rsingleTag匹配单标签的,$("<li>"),$("<li></li>")
          if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {

            //$("<li>",{title:"hi",html:"abcd"})  针对这种情况的,context 为json对象。
            for ( match in context ) {
              //如果属性是jQuery方法,就执行方法
              if ( jQuery.isFunction( this[ match ] ) ) {
                this[ match ]( context[ match ] );

              
              } else {

                //如果不是方法,就设置属性。
                this.attr( match, context[ match ] );
              }
            }
          }

          return this;

         
        }

        else {
          elem = document.getElementById( match[2] );

          // Blackberry 4.6:elem存在,但是页面上没有,所以添加了elem.parentNode,如果都满足,则elem一定存在页面上。
          
          if ( elem && elem.parentNode ) {
            this.length = 1;
            this[0] = elem;
          }

          this.context = document;
          this.selector = selector;    //"#div"
          return this;
        }

     
      }

      else if ( !context || context.jquery ) {
          return ( context || rootjQuery ).find( selector );  //rootjQuery  = $(document)

          // 处理这种$(expr, context),context是否是jQuery对象(context.jquery存在就是jQuery对象),会转换成$(context).find(expr)

          //或者$(expr),会转换成$(document).find(expr)
      }

      else {   //如果context存在,但是不是jQuery对象,就执行
          return this.constructor( context ).find( selector );   //新建jQuery对象,并调用find方法
      }       

    }

    else if ( selector.nodeType ) {       //如果是dom节点,比如:$(document)  
          this.context = this[0] = selector;
          this.length = 1;
          return this;

    }

    else if ( jQuery.isFunction( selector ) ) {     //文档加载有两种方式:$(function(){});$(document).ready(function(){});
          return rootjQuery.ready( selector );
    }

    if ( selector.selector !== undefined ) {      //$($("#div1")),当传入jQuery对象时
        this.selector = selector.selector;
        this.context = selector.context;
    }

    return jQuery.makeArray( selector, this );     //传入数组和json对象时,比如:$([]),$({})

    //makeArray把selector(类数组)转换成数组(外部使用),当传入第二个参数时(内部使用),就会转换成jQuery对象的形式。

  },

  length:0,    //匹配到的元素的长度,默认为0.

  ......

};

加油!

jquery源码解析:jQuery原型方法init的详解的更多相关文章

  1. jQuery 源码解析(三十) 动画模块 $.animate()详解

    jQuery的动画模块提供了包括隐藏显示动画.渐显渐隐动画.滑入划出动画,同时还支持构造复杂自定义动画,动画模块用到了之前讲解过的很多其它很多模块,例如队列.事件等等, $.animate()的用法如 ...

  2. jQuery 源码分析(十九) DOM遍历模块详解

    jQuery的DOM遍历模块对DOM模型的原生属性parentNode.childNodes.firstChild.lastChild.previousSibling.nextSibling进行了封装 ...

  3. jQuery 源码解析(三) pushStack方法 详解

    该函数用于创建一个新的jQuery对象,然后将一个DOM元素集合加入到jQuery栈中,最后返回该jQuery对象,有三个参数,如下: elems Array类型 将要压入 jQuery 栈的数组元素 ...

  4. jQuery 源码分析(十) 数据缓存模块 data详解

    jQuery的数据缓存模块以一种安全的方式为DOM元素附加任意类型的数据,避免了在JavaScript对象和DOM元素之间出现循环引用,以及由此而导致的内存泄漏. 数据缓存模块为DOM元素和JavaS ...

  5. jQuery源码分析(九) 异步队列模块 Deferred 详解

    deferred对象就是jQuery的回调函数解决方案,它解决了如何处理耗时操作的问题,比如一些Ajax操作,动画操作等.(P.s:紧跟上一节:https://www.cnblogs.com/grea ...

  6. 十七.jQuery源码解析之入口方法Sizzle(1)

    函数Sizzle(selector,context,results,seed)用于查找与选择器表达式selector匹配的元素集合.该函数是选择器引擎的入口. 函数Sizzle执行的6个关键步骤如下: ...

  7. jQuery 源码解析二:jQuery.fn.extend=jQuery.extend 方法探究

    终于动笔开始 jQuery 源码解析第二篇,写文章还真是有难度,要把自已懂的表述清楚,要让别人听懂真的不是一见易事. 在 jQuery 源码解析一:jQuery 类库整体架构设计解析 一文,大致描述了 ...

  8. jquery源码解析:代码结构分析

    本系列是针对jquery2.0.3版本进行的讲解.此版本不支持IE8及以下版本. (function(){ (21, 94)     定义了一些变量和函数,   jQuery = function() ...

  9. JQuery源码解析(一)

    写在前面:本<JQuery源码解析>系列是基于一些前辈们的文章进行进一步的分析.细化.修改而写出来的,在这边感谢那些慷慨提供科普文档的技术大拿们. 要查阅JQ的源文件请下载开发版的JQ.j ...

随机推荐

  1. 【jdbc】【c3p0】c3p0三种配置方式【整理】

    c3p0三种配置方式 c3p0的配置方式分为三种,分别是1.setters一个个地设置各个配置项2.类路径下提供一个c3p0.properties文件3.类路径下提供一个c3p0-config.xml ...

  2. JS中深拷贝数组、对象、对象数组方法(转载)

    我们在JS程序中需要进行频繁的变量赋值运算,对于字符串.布尔值等可直接使用赋值运算符 “=” 即可,但是对于数组.对象.对象数组的拷贝,我们需要理解更多的内容. 首先,我们需要了解JS的浅拷贝与深拷贝 ...

  3. Hibernate事务代码规范写法

    ----------------siwuxie095 事务相关概念 1.什么是事务 逻辑上的一组操作,构成这组操作的各个单元,要么一起成功, 要么一起失败 2.事务的四个特性 1)原子性 2)一致性 ...

  4. NSArray & NSDictionary

    一.NSArray 1.1 简单创建方法由难到简 NSArray *arr = [[NSArray alloc] init]; NSArray *arr = [NSArray arrayWithObj ...

  5. Linux 下启动两个tomcat

    Linux 下启动两个tomcat 闲来无事学习nginx,想要配置个load balance.可是先决条件是:得有两个web容器.两个电脑是不用想了.只能想办法在一个机器上启动两个tomcat.原以 ...

  6. 优化mysql slave的同步速度

    测试环境:Red Hat Enterprise Linux Server release 6.3 (Santiago)Server version: 5.6.22-log MySQL Communit ...

  7. zabbix结合grafana

    一.下载grafana 下载地址: http://docs.grafana.org/installation/rpm/ https://s3-us-west-2.amazonaws.com/grafa ...

  8. yii2.0 报错Cookievalidationkey Must Be Configured With A Secret Key

    'components' => [ 'request' => [ // !!! insert a secret key in the following (if it is empty) ...

  9. code1796 社交网络

    输入描述 Input Description 输入文件中第一行有两个整数,n 和 m,表示社交网络中结点和无向边的数 目.在无向图中,我们将所有结点从 1 到 n 进行编号. 接下来 m 行,每行用三 ...

  10. WCF和ASP.NET Web API在应用上的选择(转)

    出处:http://www.cnblogs.com/shanyou/archive/2012/09/26/2704814.html 在最近发布的Visual Studio 2012及.NET 4.5中 ...