JQuery源码解析-添加JQuery的一些方法和属性

在这部分中,主要是添加一些JQ的方法和属性,如:

JQuery:2.0.3 JQ版本

constructor:JQuery 重新指向JQ构造函数

init(): 初始化和参数管理的方法。

selector:存储选择字符串

length:this对象的长度

toArray():转换数组的方法

未完

代码解析:

这部分的代码都包含在

jQuery.fn = jQuery.prototype = {
};

首先是对JQ版本的赋值和重指向:

jquery: core_version,
constructor: jQuery,

这里需要住的是重指向,看如下代码:

 function Obj() {
        }

        Obj.prototype.age = 10;
        var o1 = new Obj();
        console.log(o1.constructor); //function Obj(){}

        function ObjNew() {
        }
        ObjNew.prototype = {
            age:10
        }
        var o1New = new ObjNew();
        console.log(o1New.constructor); //function Object(){}

运行代码可以看到,第二种通过字面量赋值的方式,对象上的constructor会丢失。因为这种方式是将原型上的对象进行覆盖操作,而不是添加。所以在JQ源码中需要重新指定一下。

INIT方法:

init方法是JQ最先执行的方法,通过这段代码进行调用:

jQuery = function( selector, context ) {
        // The jQuery object is actually just the init constructor ‘enhanced‘
        return new jQuery.fn.init( selector, context, rootjQuery );
    },

init方法会接收三个参数,分别是:

selector:$()括号中的第一个参数。如:"#id" ".class" "<li>" document  function()等

context:执行的上下文

rootJquery:JQ的根对象。

然后定义变量,并检查selector是否为空也就是对 $(""),$(null),$(undefind),$(false) 进判断。

var match, elem;

// HANDLE: $(""), $(null), $(undefined), $(false)
if ( !selector ) {
      return this;
}

通过校验之后,接着是判断selector的类型:

if ( typeof selector === "string" ) {
    //实现代码
} else if ( selector.nodeType ) {
    //实现代码
} else if ( jQuery.isFunction( selector ) ) {
    //实现代码
}

依次对字符串、节点、函数进行判断,并分别进行了单独的处理

先对字符串中的代码进行解析:

if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
                // Assume that strings that start and end with <> are HTML and skip the regex check
                match = [ null, selector, null ];

            } else {
                match = rquickExpr.exec( selector );
            }

首先对字符串进行判断,如果传入的selector是"<li>"或"<li>1</li><li>2</li>"这种形式想要创建节点的,则 match=[null,"<li>",null]或则 match=[null,"<li>1</li><li>2</li>",null]

否则进行正则匹配,例如:$("#id"),$(".class"),$("div") 这种形式的。

match=null;//$(".class") $("div") $("#div div.class")

match=["#id",null,"id"]  //$("#id")

match=["<li>hello","<li>",null] //$("<li>hello")

这里先对JQ的内部执行有一个说明,例如:$("li").css("background","red") 这段代码,对页面上的所有li的背景颜色赋值。那么这句代码的两部分分别做了什么处理呢。

首先 $("li") 其实是选择了页面上所有的li,并返回了一个this对象存放这些li的节点,

然后通过这个对象在对.css方法进行调用,在css方法内部的实现类似于:

for(var i=0;i<this.length;i++){
  this[i].style.background="red";
}

了解完这个过程在看下面的代码:

if ( match && (match[1] || !context) ) {  
}

这个判断首先判断math不为null,并且match[1]有值,那么这就代表创建标签的语句满足条件,或者context为空,context为空代表是选择id,因为id没有上下文,所以满足这个条件的有:

$("<li>"),$("#id")

接下来在条件里进一步判断:

if ( match && (match[1] || !context) ) {

    // HANDLE: $(html) -> $(array)
    if ( match[1] ) { //判断是创建标签还是id

        } else {      //id执行这

          }    

在这个条件里又将创建标签和查找id区分。

先看创建标签的源码:

    context = context instanceof jQuery ? context[0] : context;

                    // scripts is true for back-compat
                    jQuery.merge( this, jQuery.parseHTML(
                        match[1],
                        context && context.nodeType ? context.ownerDocument || context : document,
                        true
                    ) );

这段代码中,先将context赋值,在创建标签时,有是可能需要第二参数,这个第二个参数也就是执行上下文,例如:$("<li>",document) 一般很少这样使用,但是当页面中有iframe时,想在iframe中创建,那么第二参数设置为iframe后,就在iframe中创建了。

context instanceof jQuery ? context[0] : context 这句目的就是将context赋值为原生的节点,当我传递参数时,可能会:

1、$("<li>",document)

2、$("<li>",$(document))

这两种形式,同过这判断是否用第二种形式传入,如果是,则将原生的document对象赋值。

然后用到两个方法:jQuery.merge和jQuery.parseHTML方法。

先说一下jQuery.parseHTML方法,代码如下:

  var str = "<li>1</li><li>2</li><li>3</li><li>4</li><li>5</li>";
        var arr = jQuery.parseHTML(str, document, true);
        console.log(arr);

执行结果为,如图:

可以看到这个方法是将字符串转换为数组的形式。需要特别注意的最后一个参数,默认为false,为false代表不可以插入script代码,为true则代表可以。

再看下jQuery.merge方法

这个方法常用的功能就是将两个数组合并,如:

     var arry1 = ["a", "b"];
        var arry2 = ["c", "d"];
        var arry3 = jQuery.merge(arry1, arry2);
        console.log(arry3); //["a", "b", "c", "d"]

但这里的this对象是个json对象,通过他也可以进行合并。并返回jq想要的json格式。如:

  var arry1 = {
            0: "a",
            1: "b",
            length:2
        };
        var arry2 = ["c", "d"];
        var arry3 = jQuery.merge(arry1, arry2);
        console.log(arry3); 

结果如下:

接下来处理特殊的形式,也是很少使用的一种创建标签的方式,代码如下:

if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
                        for ( match in context ) {
                            // Properties of context are called as methods if possible
                            if ( jQuery.isFunction( this[ match ] ) ) {
                                this[ match ]( context[ match ] );

                            // ...and otherwise set as attributes
                            } else {
                                this.attr( match, context[ match ] );
                            }
                        }
                    }

这种匹配的是:$("<li>",{title:"hello",html:"aaaaaaa"}) 后面有个json对象当参数的方式。

如果是这种方式的话,那么会循环这个json对象,先判断json里的属性是否是jq自带的方法,如果是,则直接调用方法,否则,进去else,用jq的attr方法为这个标签加一个属性。

到这里创建标签的方式就介绍完了。下面介绍一下传入id形式的代码。

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

                    // Check parentNode to catch when Blackberry 4.6 returns
                    // nodes that are no longer in the document #6963
                    if ( elem && elem.parentNode ) {
                        // Inject the element directly into the jQuery object
                        this.length = 1;
                        this[0] = elem;
                    }

                    this.context = document;
                    this.selector = selector;
                    return this;

代码很简单,但需要注意一下判断,这是为了最黑莓浏览器的兼容,因为在黑莓4.6版本的浏览器中,当删除节点之后,还可以用js代码查找到这个节点,

所以需要进行一下父节点的判断,因为任何节点都会有父节点。

接下来也是返回一个JQ需要的特殊json格式。赋值长度为1,第一个对象是当前查找到的对象。然后把上下文赋值document,赋值selector。

到这里已经把创建标签和id查找的源码分析完了,其他复杂查找的代码会进入下面的代码:

    } else if ( !context || context.jquery ) {
                return ( context || rootjQuery ).find( selector );

            // HANDLE: $(expr, context)
            // (which is just equivalent to: $(context).find(expr)
            } else {
                return this.constructor( context ).find( selector );
            }

这段代码的判断就是要保证$("ul",document).find("li")  $("ul",$(document)).find("li")  这两种形式,都会执行:jQuery(document).find();这个方法。

到这就把当参数是字符串传入时,要执行的代码解析完了,下面分析传入节点或者方法时要执行的代码。

时间: 2024-10-01 06:39:09

JQuery源码解析-添加JQuery的一些方法和属性的相关文章

五.jQuery源码解析之jQuery.extend(),jQuery.fn.extend()

给jQuery做过扩展或者制作过jQuery插件的人这两个方法东西可能不陌生.jQuery.extend([deep],target,object1,,object2...[objectN]) jQuery.fn.extend([deep],target,object1,,object2...[objectN])这两个属性都是用于合并两个或多个对象的属性到target对象.deep是布尔值,表示是否进行深度合并,默认是false,不执行深度合并.通过这种方式可以在jQuery或jQuery.fn

四.jQuery源码解析之jQuery.fn.init()的参数解析

从return new jQuery.fn.init( selector, context, rootjQuery )中可以看出 参数selector和context是来自我们在调用jQuery方法时传过来的.那么selector和context都有哪些可能. 对于表格中的4~9行中的可能做具体分析. 如果selector是字符串,则首先检测是html代码还是#id. 126行的if语句:以"<"开头,以">"结尾,且长度>=3.则假设额这个是HT

jquery源码解析:jQuery对元素属性的操作2

这一课,我们将继续讲解jQuery对元素属性操作的方法. 首先,我们先看一下这几个方法是如何使用的: $("#div1").addClass("box1 box2");     //给元素div的class属性添加box1和box2 $("#div1").removeClass("box1");     //删除元素div的class属性值box1 $("#div1").toggleClass("

jquery源码解析:jQuery工具方法when详解

我们先来看when方法是如何使用的: var cb = $.when();   //when方法也是返回一个延迟对象,源码是return deferred.promise();返回的延迟对象不能修改状态 $.Deferred()也是返回一个延迟对象,那么它们的区别是什么呢?$.Deferred()只能针对一个延迟对象做成功,失败,进行中的操作,而$.when()可以针对多个延迟对象做以上操作.举个例子: function a(){ var cb = $.Deferred(); cb.resolv

jquery源码解析:jQuery工具方法Callbacks详解

我们首先来讲下Callbacks是如何使用的:第一个例子 function a(){} function b(){} var cb = $.Callbacks(); cb.add(a); cb.add(b); cb.fire();      //就会先执行a方法,再执行b方法 上面大概的意思是:add方法,就是把方法添加到数组list中,每执行一次,就添加一个方法.而fire方法,就是把list数组中的方法按顺序执行. 使用场景:第二个例子 function a(n){ } (function(

jquery源码解析:jQuery数据缓存机制详解1

jQuery中有三种添加数据的方法,$().attr(),$().prop(),$().data().但是前面两种是用来在元素上添加属性值的,只适合少量的数据,比如:title,class,name等.对于json这种数据量大的,就适合用data方法来添加,而data方法就是jQuery缓存机制最重要的方法. jQuery中为什么要用缓存机制系统呢?因为DOM元素与js对象之间互相引用,在大部分浏览器下会引起内存泄漏.为了解决这个问题,jQuery就写了一个缓存机制系统.举个例子: var di

jquery源码解析:jQuery静态属性对象support详解

jQuery.support是用功能检测的方法来检测浏览器是否支持某些功能.针对jQuery内部使用. 我们先来看一些源码: jQuery.support = (function( support ) { ...... return support;})( {} ); jQuery.support其实就是一个json对象.在火狐浏览器下,打印出support对象: 接下来,我们来看它的源码 jQuery.support = (function( support ) { var input = d

jquery源码解析:jQuery队列操作queue方法实现的原理

我们先来看一下jQuery中有关队列操作的方法集: 从上图可以看出,既有静态方法,又有实例方法.queue方法,相当于数组中的push操作.dequeue相当于数组的shift操作.举个例子: function aaa(){ alert(1); } function bbb(){ alert(2); } $.queue(document,"q1",aaa);   //在document下创建一个队列q1,并往q1队列中添加aaa函数. $.queue(document,"q1

jQuery源码解析(jQuery对象的实例属性和方法)

1.记录版本号 以及 修正constructor指向 jquery: core_version, constructor: jQuery, 因为jQuery.prototype={ ... } 这种写法将自动生成的jQuery.prototype.constructor属性覆盖删除,所以需要重新修正(指向其构造函数 jQuery).2.init() 初始化方法: init()方法最终返回的是this -jQuery(其实是jQuery.prototype.init)方法的实例对象. 实例对象继承