当前位置: 移动技术网 > IT编程>开发语言>Jquery > jQuery源码学习笔记二

jQuery源码学习笔记二

2018年10月31日  | 移动技术网IT编程  | 我要评论
javascript // js源码在构造函数创建完就自动生成了 function Aaa(){}; Aaa.prototype.constructor = Aaa; var a = new Aaa(); alert(a.constructor); // function Aaa(){}; Aaa. ...
//添加实例属性和方法
jquery.fn = jquery.prototype = {
    // 版本,使用方式:$().jquery弹出当前引入的jquery的版本
    jquery: core_version,
    // 修正指向问题(后有详解)
    constructor: jquery,

    // 初始化和参数管理
    init: function( selector, context, rootjquery ) {
        var match, elem;

        // 写错之后的处理,如果写成: $(""), $(null), $(undefined), $(false),直接返回
        if ( !selector ) {
            return this;
        }
        // 对字符串进行处理
        if ( typeof selector === "string" ) {
            // 如果是这种$('<li>')或$('<li>1</li><li>2</li>')
            if ( selector.charat(0) === "<" && selector.charat( selector.length - 1 ) === ">" && selector.length >= 3 ) {
                // match = [ null, '<li>', null ];或者 match = [ null, '<li>1</li><li>2</li>', null ];
                match = [ null, selector, null ];
             //如果是$('#div1') $('.box') $('div')  $('#div1 div.box')
            } else {
                //$('.box') $('div') $('#div1 div.box')  match = null;
                //$('#div1') match = ['#div1',null,'div1'];
                //$('<li>hello')  match = ['<li>hello','<li>',null];
                 match = rquickexpr.exec( selector );  //exec()后面详解
            }
            
                  // $('<li>')  $('#div1') //$('#div1')的上下文为空,即context为false
             if ( match && (match[1] || !context) ) {   
               if ( match[1] ) {
                    // 如果是$('<li>',document)填写了第二个对象,并且第二个对象是原生,则直接返回该对象;$('<li>',$(document))如果返回的第二个对象是jquery,则将它转换成原生的对象 
                    context = context instanceof jquery ? context[0] : context;
                    // 1、jquery.parsehtml()函数用于将html字符串解析为对应的dom节点数组;使用一个html字符串创建一个数组的dom节点
                    jquery.merge( this, jquery.parsehtml(
                        match[1],  //需要解析并转成dom节点数组的html字符串
                        //指定在哪个document中创建元素,默认为当前文档的document,可能是iframe
                        context && context.nodetype ? context.ownerdocument || context : document,
                        //true,boolean类型指定传入的html字符串中是否包含脚本,默认为false
                        true
                    ) );

                    // 1、rsingletag.test( match[1] )匹配单标签,只能匹配<li>或<li></li>,其他都不行
                    // 2、jquery.isplainobject( context )函数用于判断指定参数是否是一个纯粹的对象。{ } 或new object()或{ name: "codeplayer"}
                    if ( rsingletag.test( match[1] ) && jquery.isplainobject( context ) ) {
                        for ( match in context ) {
                            // jquery.isfunction用于判断参数是否是一个函数
                            if ( jquery.isfunction( this[ match ] ) ) {
                                //如果是函数就直接调用该函数,示例:$('<li></li>',{title : 'hi',html : 'abcd',css : {background:'red'}}).appendto( 'ul' );其中html : 'abcd'就相当于this.html('abcd')
                                this[ match ]( context[ match ] );
                            } else {
                                //如果不是函数就直接添加属性
                                this.attr( match, context[ match ] );
                            }
                        }
                    }

                    return this;

                //  $('#div1')选择元素
                } else {
                    elem = document.getelementbyid( match[2] );

                    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;
                }

        
            } else if ( !context || context.jquery ) {
                return ( context || rootjquery ).find( selector );
            
            } else {
                return this.constructor( context ).find( selector );
            }

        //对dom元素进行处理,$(this),$(document)。
        //nodetype属性返回以数字值返回指定节点的节点类型。如果是元素节点,返回1;如果是属性节点,返回2
        } else if ( selector.nodetype ) {
            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 ) {
            this.selector = selector.selector;
            this.context = selector.context;
        }
        // jquery.makearray()函数用于将一个类数组对象转换为真正的数组对象(详解)
        return jquery.makearray( selector, this );
    },
    // selector 存储选择字符串;
    selector: "",
    // length this对象的长度
    length: 0,
    // toarray 专数组
    toarray: function() {
        return core_slice.call( this );
    },

    // get 转原生合集
    get: function( num ) {
        return num == null ?

            // return a 'clean' array
            this.toarray() :

            // return just the object
            ( num < 0 ? this[ this.length + num ] : this[ num ] );
    },


    // pushstack jq对象的入栈(先进后出)
    pushstack: function( elems ) {

        // build a new jquery matched element set
        var ret = jquery.merge( this.constructor(), elems );

        // add the old object onto the stack (as a reference)
        ret.prevobject = this;
        ret.context = this.context;

        // return the newly-formed element set
        return ret;
    },


    // each 遍历集合
    each: function( callback, args ) {
        return jquery.each( this, callback, args );
    },
    // dom加载接口
    ready: function( fn ) {
        jquery.ready.promise().done( fn );

        return this;
    },
    // 集合的截取
    slice: function() {
        return this.pushstack( core_slice.apply( this, arguments ) );
    },
    // 集合的第一项
    first: function() {
        return this.eq( 0 );
    },
    // 集合的最后一项
    last: function() {
        return this.eq( -1 );
    },
    // 集合的指定项
    eq: function( i ) {
        var len = this.length,
            j = +i + ( i < 0 ? len : 0 );
        return this.pushstack( j >= 0 && j < len ? [ this[j] ] : [] );
    },
    // 返回新集合
    map: function( callback ) {
        return this.pushstack( jquery.map(this, function( elem, i ) {
            return callback.call( elem, i, elem );
        }));
    },
    // 返回集合前一个状态
    end: function() {
        return this.prevobject || this.constructor(null);
    },

    // push、sort、splice内部使用
    push: core_push,
    sort: [].sort,
    splice: [].splice
};

部分详解

1、constructor: jquery
示例:

// js源码在构造函数创建完就自动生成了
function aaa(){};
    aaa.prototype.constructor = aaa;
    var a = new aaa();
    alert(a.constructor);  // function aaa(){};

    aaa.prototype.constructor = array;
    alert(a.constructor);  // function array() { [native code] }

    aaa.prototype = {
        constructor : aaa,
        name : 'hello',
        age : 30
    };
    var a1 = new aaa();
    alert(a1.constructor);  // function aaa(){};

这个constructor属性非常容易被不小心修改掉,所以jquery需要修正指向

2、match = rquickexpr.exec( selector )
示例:

var  rquickexpr = /^(?:\s*(<[\w\w]+>)[^>]*|#([\w-]*))$/;
var selector = "#div1";
var match = rquickexpr.exec( selector );
console.log(match);      //match = ['#div1',null,'div1'];

exec() 方法就是用来检索字符串中正则表达式的匹配,如果匹配到了那么就返回一个存放有结果的数组,如果没有匹配到就返回一个null;
match是数组,第0个元素是与正则表达式相匹配的文本,第1个元素是与正则表达式的第1个子表达式相匹配的文本(如果有的话),第2个元素是第2个子表达式相匹配的文本(如果有的话),第3个元素是第3个子表达式相匹配的文本(如果有的话),这里就是元素的id,不包含#。

3、jquery.makearray()
var adiv = document.getelementsbytagname('div');
adiv并不是一个真正的数组,可以用$.makearray(adiv)转成一个数组 ;$.makearray(adiv,{length:0})将它转成一个对象
$([]) $({})

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网