zoukankan      html  css  js  c++  java
  • jquery1.7.2的源码分析(一)

    说到jquery可能是大家最经常用到的,在日常的编写程序中最经常使用到,在使用jquery插件的同时,深入的解读jquery源码有利于我们学到设计的思想和实现的技巧

    在jquery源码的分析中,其中艾伦 Aaron的博客有深入的介绍,其在慕课网上也有相应的源码的解读,感兴趣的同学可以去看看

    此博客是鉴于自己对jquery的学习中的所记录的,学习的jquery源码

    jquery源码整体分析

    //采用闭包传入window
    (function( window, undefined ) {//doing something})(window)
    
     var document = window.document,
    navigator = window.navigator,
    location = window.location;
    var jQuery = (function() {
    // Define a local copy of jQuery
    //构造函数
    var jQuery = function( selector, context ) {
    // The jQuery object is actually just the init constructor 'enhanced'
    //注意这是是new 一个 init
    return new jQuery.fn.init( selector, context, rootjQuery );
    },
    // Map over jQuery in case of overwrite
    _jQuery = window.jQuery,
    // Map over the $ in case of overwrite
    _$ = window.$,
    // A central reference to the root jQuery(document)
    rootjQuery,
    // A simple way to check for HTML strings or ID strings
    // Prioritize #id over tag to avoid XSS via location.hash (#9521)
    quickExpr = /^(?:[^#<]*(<[wW]+>)[^>]*$|#([w-]*)$)/,
    // Check if a string has a non-whitespace character in it
    //不为空白符
    rnotwhite = /S/,
    //匹配首字母以空白符开始的
    // 匹配末尾以空白符结束的
    trimLeft = /^s+/,
    trimRight = /s+$/,
    //匹配一个独立的标签如div
    如,
    rsingleTag = /^<(w+)s*/?>(?:</1>)?$/,
    // JSON RegExp
    rvalidchars = /^[],:{}s]*$/,
    rvalidescape = /\(?:["\/bfnrt]|u[0-9a-fA-F]{4})/g,
    rvalidtokens = /"[^"\
    
    ]*"|true|false|null|-?d+(?:.d*)?(?:[eE][+-]?d+)?/g,
    rvalidbraces = /(?:^|:|,)(?:s*[)+/g,
    // Useragent RegExp浏览器的正则表达式
    rwebkit = /(webkit)[ /]([w.]+)/,
    ropera = /(opera)(?:.*version)?[ /]([w.]+)/,
    rmsie = /(msie) ([w.]+)/,
    rmozilla = /(mozilla)(?:.*? rv:([w.]+))?/,
    // Matches dashed string for camelizing
    rdashAlpha = /-([a-z]|[0-9])/ig,
    rmsPrefix = /^-ms-/,
    //驼峰式
    fcamelCase = function( all, letter ) {
    return ( letter + "" ).toUpperCase();
    },
    // Keep a UserAgent string for use with jQuery.browser
    userAgent = navigator.userAgent,
    // For matching the engine and version of the browser
    browserMatch,
    // The deferred used on DOM ready
    readyList,
    // The ready event handler
    DOMContentLoaded,
    // Save a reference to some core methods
    toString = Object.prototype.toString,
    hasOwn = Object.prototype.hasOwnProperty,
    push = Array.prototype.push,
    slice = Array.prototype.slice,
    trim = String.prototype.trim,
    indexOf = Array.prototype.indexOf,
    // [[Class]] -> type pairs
    class2type = {};
    jQuery.fn = jQuery.prototype = {
    constructor: jQuery,
    init: function( selector, context, rootjQuery ) {
    var match, elem, ret, doc;
    // Handle $(""), $(null), or $(undefined)
    if ( !selector ) {
    return this;
    }
    // Handle $(DOMElement)
    if ( selector.nodeType ) {
    //先保持疑问
    this.context = this[0] = selector;
    this.length = 1;
    return this;
    }
    // The body element only exists once, optimize finding it
    if ( selector === "body" && !context && document.body ) {
    this.context = document;
    this[0] = document.body;
    this.selector = selector;
    this.length = 1;
    return this;
    }
    // Handle HTML strings
    if ( typeof selector === "string" ) {
    // Are we dealing with HTML string or an ID?
    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 = quickExpr.exec( selector );
    }
    // Verify a match, and that no context was specified for #id
    if ( match && (match[1] || !context) ) {
    // HANDLE: $(html) -> $(array)
    if ( match[1] ) {
    context = context instanceof jQuery ? context[0] : context;
    doc = ( context ? context.ownerDocument || context : document );
    // If a single string is passed in and it's a single tag
    // just do a createElement and skip the rest
    ret = rsingleTag.exec( selector );
    if ( ret ) {
    if ( jQuery.isPlainObject( context ) ) {
    selector = [ document.createElement( ret[1] ) ];
    jQuery.fn.attr.call( selector, context, true );
    } else {
    selector = [ doc.createElement( ret[1] ) ];
    }
    } else {
    ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
    selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
    }
    return jQuery.merge( this, selector );
    // HANDLE: $("#id")
    } else {
    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 ) {
    // Handle the case where IE and Opera return items
    // by name instead of ID
    if ( elem.id !== match[2] ) {
    return rootjQuery.find( selector );
    }
    // Otherwise, we inject the element directly into the jQuery object
    this.length = 1;
    this[0] = elem;
    }
    this.context = document;
    this.selector = selector;
    return this;
    }
    // HANDLE: $(expr, $(...))
    } 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 );
    }
    // HANDLE: $(function)
    // Shortcut for document ready
    } else if ( jQuery.isFunction( selector ) ) {
    return rootjQuery.ready( selector );
    }
    if ( selector.selector !== undefined ) {
    this.selector = selector.selector;
    this.context = selector.context;
    }
    return jQuery.makeArray( selector, this );
    },
    // Start with an empty selector
    selector: "",
    // The current version of jQuery being used
    jquery: "1.7.2",
    // The default length of a jQuery object is 0
    length: 0,
    // The number of elements contained in the matched element set
    size: function() {
    //元素的个数
    return this.length;
    },
    toArray: function() {
    //可以将jquery对象转化为dom对象
    return slice.call( this, 0 );
    },
    // Get the Nth element in the matched element set OR
    // Get the whole matched element set as a clean array
    get: function( num ) {
    return num == null ?
    // Return a 'clean' array
    //
    this.toArray() :
    // Return just the object
    //例如:$('div').get(0)取到一个div
    ( num < 0 ? this[ this.length + num ] : this[ num ] );
    },
    // Take an array of elements and push it onto the stack
    // (returning the new matched element set)
    pushStack: function( elems, name, selector ) {
    // Build a new jQuery matched element set
    var ret = this.constructor();
    if ( jQuery.isArray( elems ) ) {
    push.apply( ret, elems );
    } else {
    jQuery.merge( ret, elems );
    }
    // Add the old object onto the stack (as a reference)
    ret.prevObject = this;
    ret.context = this.context;
    //eg.div.slice(0,2)
    //console.log:[div, div, prevObject: init[3], context: document, selector: "div.slice(0,2)"]
    if ( name === "find" ) {
    ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
    } else if ( name ) {
    ret.selector = this.selector + "." + name + "(" + selector + ")";
    }
    return ret;
    },
    // Execute a callback for every element in the matched set.
    // (You can seed the arguments with an array of args, but this is
    // only used internally.)
    each: function( callback, args ) {
    return jQuery.each( this, callback, args );
    },
    ready: function( fn ) {
    // Attach the listeners
    jQuery.bindReady();
    // Add the callback
    readyList.add( fn );
    return this;
    },
    eq: function( i ) {
    i = +i;
    return i === -1 ?
    this.slice( i ) :
    this.slice( i, i + 1 );
    },
    first: function() {
    return this.eq( 0 );
    },
    last: function() {
    return this.eq( -1 );
    },
    slice: function() {
    return this.pushStack( slice.apply( this, arguments ),
    "slice", slice.call(arguments).join(",") );
    },
    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);
    },
    // For internal use only.
    // Behaves like an Array's method, not like a jQuery method.
    push: push,
    sort: [].sort,
    splice: [].splice
    };
    // Give the init function the jQuery prototype for later instantiation
    jQuery.fn.init.prototype = jQuery.fn;
    
  • 相关阅读:
    Remove Duplicates from Sorted Array
    Longest Valid Parentheses
    Valid Parentheses
    Java [Leetcode 112]Path Sum
    Java [Leetcode 119]Pascal's Triangle II
    Java [Leetcode 102]Binary Tree Level Order Traversal
    Java [Leetcode 172]Factorial Trailing Zeroes
    奇异值分解(转载)
    Java [Leetcode 118]Pascal's Triangle
    Java [Leetcode 66]Plus One
  • 原文地址:https://www.cnblogs.com/heyinwangchuan/p/6243461.html
Copyright © 2011-2022 走看看