zoukankan      html  css  js  c++  java
  • jquery源码解析:jQuery原型方法init的详解

    先来了解几个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.

      ......

    };

    加油!

  • 相关阅读:
    bootstrap 按钮 文本 浮动 隐藏
    bootstrap 表单控件 控件状态 控件大小 help-block
    wps 操作
    SSH中的免password登录
    Qt音乐播放器制作(二)Easy Player
    云计算资源分享与下载
    uva11059(最大乘积)
    两小时搞定C#版超级战舰游戏
    数据库中的參照完整性(Foreign Key)
    动手解决困扰自己的事情——记屏蔽网页广告
  • 原文地址:https://www.cnblogs.com/chaojidan/p/4136291.html
Copyright © 2011-2022 走看看