码迷,mamicode.com
首页 > Web开发 > 详细

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

时间:2016-09-08 14:22:11      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:

在这部分中,主要是添加一些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();这个方法。

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

 

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

标签:

原文地址:http://www.cnblogs.com/y8932809/p/5852649.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!