zoukankan      html  css  js  c++  java
  • jQuery2.0.3源码

    概览

      整体结构

    (function (){
       (21  , 94) 定义了一些变量和函数 jQuery=function();  
       (96  , 293) 给jQuery对象添加一些方法和属性;  
       (285 , 347) extend:jQuery扩展方法;  
       (349 , 817) jQuery.extend : 扩展一些工具方法;  
       (877 , 2856 ) Sizzle : 复杂选择器的实现;  
       (2880, 3042 ) Callbacks : 回调对象:函数的统一管理  
       (3043, 3183 ) Deferred : 延迟对象:对异步的统一管理  
       (3184, 3295) support : 浏览器功能检测,确定浏览器对某些功能是否支持  
       (3380, 3652) data() : 数据缓存功能  
       (3653, 3797) queue()/dequeue() : 队列管理  
       (3803, 4299) attr() prop() val() addClass()等方法,对元素属性的操作  
       (4300, 5138) on() trigger()等方法,事件相关的方法,事件管理  
       (5140,6057) DOM操作:添加 删除 包装 获取 DOM筛选  
       (6058, 6620) css() : 样式操作  
       (6621, 7854) 提交的数据和Ajax()操作:ajax() load() getJson()  
       (7855, 8584) animite() : 运动的方法  
       (8585, 8792) offset() :位置与尺寸的方法  
       (8804, 8821) JQuery对模块化的支持  
       (8826) window.jQuery = window.$ = jQuery;//对外提供的接口  
    })();

    匿名函数 :14

    (function (window,undefined){
        //......
    })(window)

    为什么传入window

    1:为了便于压缩 2:当方法内部使用的时候,查找的速度快。

    为什么传入undefined

    防止undefined在外部被修改

    var undefined=1

    如果这样赋值,那undefined的值从此以后变为1,影响以后的判断。

    严格执行 :20

    'use strict'
    低版本不支持,.net跟踪不支持。根据项目选型决定是否开启。

    rootjQuery :23

    rootjQuery=jQuery(document);//:866

    为了压缩,可维护

    core_strundefined :30

    core_strundefined=typeof undefined

    为了支持 IE9,从而使用type of xmlNode.method代替xmlNode.method !==undefined

    变量存储 :33

    location = window.location //:33
    document=window.document
    docElem=document.documenttElement
    
    core_concat = core_deletedIds.concat, //:52
    core_push = core_deletedIds.push,
    core_slice = core_deletedIds.slice,
    core_indexOf = core_deletedIds.indexOf,
    core_toString = class2type.toString,
    core_hasOwn = class2type.hasOwnProperty,
    core_trim = core_version.trim,

    防冲突 :38

    _jQuery=window.jQuery
    _$=window.$

    class2type={} :44

    $.tpye() 会用到,clas2type形如 {'[objectt String]'}

    core_version="2.0.3" :49

    版本号

    jQuery声明

    最终$()调用的是这个

    //:61
    jQuery = function( selector, context ) {
        return new jQuery.fn.init( selector, context, rootjQuery );
    },

    jQuery 原型

    //:96
    jQuery.fn = jQuery.prototype = {
        jquery: core_version,
        constructor: jQuery,
        init: function( selector, context, rootjQuery ) {...}
    }
    //:283
    jQuery.fn.init.prototype = jQuery.fn;

    实际上jQuery.prototype.init.prototype = jQuery.prototype。之后的的代码就可以写成颗粒化的调用操作,形如jQuery().css()

    通用正则

    数字

    //:67
    core_pnum = /[+-]?(?:d*.|)d+(?:[eE][+-]?d+|)/.source,

    非空字符,比如单词

    core_rnotwhite = /S+/g,

    html标签

    防止通过location.hash的XSS注入(#9521)

    rquickExpr = /^(?:s*(<[wW]+>)[^>]*|#([w-]*))$/,

    独立空标签

    比如 <p></p>

    rsingleTag = /^<(w+)s*/?>(?:</1>|)$/,

    IE驼峰转换

    -ms-aaa-bbb转换成MsAaaBbb

    rmsPrefix = /^-ms-/,

    普通驼峰转换

    rdashAlpha = /-([da-z])/gi,

    jQuery.prototype :98

    jquery:版本 :100

    jquery: core_version,

    constructor:修正指向问题

    constructor: jQuery,
    不写容易被修改,例如

    
    //Aaa
    Aaa.prototype.name='hello'
    Aaa.prototype.age=30
    
    //Object
    AAA.prototype={
        name:'hello',
        age:30
    }

    init:初始化和参数管理 :101

    对传入的参数分别处理

    忽略的

    $(""), $(null), $(undefined), $(false)

    字符的

    if 字符左侧是`<`且右侧是`>`且长度 大于3
        //$('<li>') $('<li>1</li><li>2</li>')
        match=[null,'<li>',null]
    else
        match=null //$('.box') $('div') $('#div1 div.box')
        match=['$#div1',null,'div1']//$('#div1')
        match=['<li>hello','<li>',null] $('<li>hello')
    if ( match && (match[1] || !context) ) {// :120
        //$('<li>') $('#div1')
        if(match[1]){
            //HANDLE: $(html) -> $(array)
            使用jQuery.parseHTML将html代码转数组
            使用jQuery.merge将json转数组
            
            // HANDLE: $(html, props)
            if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) 
            
            
        }else{
            //HANDLE: $(#id) :151
            elem = document.getElementById( match[2] );
            //黑莓4.6兼容代码 :155
        }
    // HANDLE: $(expr, $(...))
    }else if ( !context || context.jquery ) {
    
    // HANDLE: $(expr, context) 例如 $(context).find(expr)
    } else {
    
    }
    // HANDLE: $(DOMElement)
    else if ( selector.nodeType ) {
    
    // HANDLE: $(function)
    else if ( jQuery.isFunction( selector ) ) {
    
    jQuery.makeArray 将dom集合转数组或对象

    selector:存储选择字符串

    length:this对象的长度

    toArray():转数组 :202

    return core_slice.call( this );
    $('div'):{0:div,1:div,length:2} =>[div,div]
    实际是调用slice

    get():转原生集合 :208

    根据num返回全部或其中某个元素

    get: function( num ) {
        return num == null ?
            this.toArray() :
            ( num < 0 ? this[ this.length + num ] : this[ num ] );
    },

    pushStack():jQ对象入栈 :220

    一个栈里放1个jQ对象,1个jQ对象包含1个或多个dom

    each():遍历集合 :236

    工具方法jQuery.each

    ready():DOM加载的接口 :240

    工具方法jQuery.reday.promise.done(fn)

    slice():集合的截取 :247

    栈操作 this.pushStack( core_slice.apply( this, arguments ) );

    first():集合的第一项

    this.eq( 0 )

    last():集合的最后一项

    this.eq( -1 )

    eq():集合的指定项

    map():返回新集合

    return this.pushStack( jQuery.map(this, function( elem, i ) {
        return callback.call( elem, i, elem );
    }));

    end():返回集合前一个状态

    return this.prevObject || this.constructor(null);

    push(): 内部使用

    core_push

    sort(): 内部使用

    [].sort,

    splice(): 内部使用

    splice: [].splice

    jQuery.extend

    拷贝方法 :285

    定义一些变量
    if(){}    看是不是深拷贝情况
    if(){}    看参数正确不
    if(){}    看是不是插件情况
    for(){    可能有多个对象情况
        if(){}        防止循环引用
        if(){}        深拷贝
        else if(){}     浅拷贝
    }

    防止循环引用

    if ( target === copy ) {
        continue;
    }

    深拷贝

    if ( copyIsArray ) {
        copyIsArray = false;
        clone = src && jQuery.isArray(src) ? src : [];
    
    } else {
        clone = src && jQuery.isPlainObject(src) ? src : {};
    }
    
    // Never move original objects, clone them
    target[ name ] = jQuery.extend( deep, clone, copy );
    

    浅拷贝

    target[ name ] = copy;

    工具方法

    jQuery.extend({
        expando:生成唯一jQ字符串(内部)
        noConflict():防止冲突
        isReady: dom是否加载完(内部)
        readyWait:等待多少文件的计数器(内部)
        holdReady(): 推迟dom触发
        ready():准备dom触发
        isFunction():是否为函数
        isArray():是否为数组
        isWindow():是否为window
        isNumberic():是否为数字
        type():判断数据类型
        isPlainObjeect():是否为对象自变量
        isEmptyObject():是否为空的对象
        error():抛出异常
        parseHTML():解析节点
        parseJSON():解析JSON
        parseXML():解析XML
        noop():空函数
        globalEval():全局解析js
    })

    expando 唯一映射 :351

    生成唯一jQuery字符串,做映射关系用

    expando: "jQuery" + ( core_version + Math.random() ).replace( /D/g, "" ),

    noConflict 防止冲突 :353

    if ( window.$ === jQuery ) {
        window.$ = _$;
    }
    if ( deep && window.jQuery === jQuery ) {
        window.jQuery = _jQuery;
    }
    return jQuery;

    dom加载相关

    jQuery.ready.promise

    if ( document.readyState === "complete" ) {
        // 防止Ie的提前执行
        setTimeout( jQuery.ready );
    } else {
        // 若dom加载了则执行,否则监听完成后执行
        document.addEventListener( "DOMContentLoaded", completed, false );
        window.addEventListener( "load", completed, false );
    }

    readyList

    holdReady(hold) :373

    为true时执行ready,否则readyWait计数

    if ( hold ) {
        jQuery.readyWait++;
    } else {
        jQuery.ready( true );
    }

    ready(wait) :382

    //如果有wait,或者ready,中止
    if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
        return;
    }
    jQuery.isReady = true;
    // 如果被触发,那么递减,如果需要则等待
    if ( wait !== true && --jQuery.readyWait > 0 ) {
        return;
    }
    //如果有函数绑定,则执行。
    readyList.resolveWith( document, [ jQuery ] );
    // 触发任何绑定事件
    if ( jQuery.fn.trigger ) {
        jQuery( document ).trigger("ready").off("ready");
    }

    type(obj) :423

    if ( obj == null ) {
        return String( obj );
    }
    // 兼容: Safari <= 5.1 
    return typeof obj === "object" || typeof obj === "function" ?
        class2type[ core_toString.call(obj) ] || "object" :
        typeof obj;

    isWindow(obj) :415

    不为空且window属性相同(undefined 没有属性)

    return obj != null && obj === obj.window;

    isNumeric(obj) :417

    typeof NaN 或 finite ==='number'

    return !isNaN( parseFloat(obj) ) && isFinite( obj );

    parseHTML(data, context, keepScripts) :475

    //校验输入
    parsed=正则匹配data
    //单标签
    return context.createElement( parsed[1] )
    //多标签
    //判断是否保留script
    parsed = jQuery.buildFragment( [ data ], context, scripts )
    return jQuery.merge( [], parsed.childNodes );

    globalEval(code) :528

    直接调用eval无法全局访问,必须先赋值

    var indirect = eval;
    if 'use strict'
        createElement
        document.head.appendChild( script ).parentNode.removeChild( script )
    else
        indirect(code)

    camelCase :552

    修正IE,驼峰转换

    return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase )

    nodeName( elem, name ) :556

    全转小写判断是否相同

    return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();

    each( obj, callback, args ) :561

    i=0
    length=obj.length //若json则不存在
    isArray=isArraylike(obj)
    
    if isArray
        for(;;)
            callback.call
    else 
        for in
            callback.call

    makeArray :615

    类数组转数组

    if isArraylike( Object(arr) 
        jQuery.merge
    else
        core_push

    inArray( elem, arr, i ) :632

    indexOf

    return arr == null ? -1 : core_indexOf.call( arr, elem, i );

    merge( first, second ) :636

    获取2个变量的length

    if 非json

    for
        first[ i++ ] = second[ j ]

    else

    while
        first[ i++ ] = second[ j++ ]

    grep( elems, callback, inv ) :656

    过滤新数组

    for
        retVal = !!callback( elems[ i ], i )
        if inv !== retVal
            ret.push( elems[ i ] )

    map( elems, callback, arg ) :676

    //分别处理arr 和json
    for
        value = callback( elems[ i ], i, arg );
        if ( value != null ) {
            ret[ ret.length ] = value;
        }
    return core_concat.apply( [], ret );

    proxy( fn, context ) :713

    context 若是string 
        content=fn(content)
    return function(){
        return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) )
    }
    proxy.guid = fn.guid = fn.guid || jQuery.guid++

    access( elems, fn, key, value, chainable, emptyGet, raw ) :742

    elems $('#div1')
    fn 回调函数
    key,value {background:'red'}

    if  type(key) ==='object'
        for
            access
    else if value !== undefined
        //空
        //非函数
        //函数

    swap( elem, options, callback, args ) :798

    设置display可见
    设置visibility:hidden
    获取样式
    属性再转回去

    isArraylike(obj) :848

    判断不是window

    nodeType==1&&length #是节点 返回true
    return type === "array" 
            ||type !== "function" 
                &&( length === 0 
                    ||typeof length === "number"
                    && length > 0 
                    && ( length - 1 ) in obj )

    createOptions(options)

    将'once memory'=>{once:true,memory:true}
    each

    obj[flag]=true
    

    jQuery.Callbacks(options) :2880

    once// fire for list
    memory//add()时直接执行
    unique//重复函数,add()时判断去重
    stopOnFalse//fire for list

    add(arg)

        分别判断arg=aaa
                arg=aaa,bbb
                arg=[aaa,bbb]
        if menory==true
            fire

    remove(arg) :2965

    分隔数组

    has(fn) :2987

    jQuery.InArray

    fireWith(context,args) :3018

        if list && ( !fired || stack )
            if firing
                stack.push(args)
            else
                fire(args)

    Deferred(func) :3045

    异步操作,延迟对象,基于$.Callbacks()
    $.ajax(url).done(=>resolve).fail(=>reject)

    "resolve", "done", jQuery.Callbacks("once memory"), "resolved"

    成功
    resolve=>fire
    done=>add

    "reject", "fail", jQuery.Callbacks("once memory"), "rejected"

    失败
    reject=>fire
    fail=>add

    "notify", "progress", jQuery.Callbacks("memory")

    notify=>fire
    progress =>add

    when() 批量延迟:3133

    内部有个计数器,当$.when(a(),b(),c()) 中的arguments.length随着done()后减少到0,实际执行$.Deferred->resolve()
    参数必须返回deferred延迟对象,不然则跳过该项。

    support 功能检测:3184

    统一兼容性问题。

    checkOn复选框value值

    老版本chrome是‘’,新的是‘on’

    optSelected下拉菜单子项第一项选中

    ie不会选中

    noCloneChecked 克隆复选框的选中状态

    ie9,10没有选中

    focusinBubbles 选中的冒泡机制

    data 数据缓存 :3308

    key 自定义属性,<div JQueryxxxx="x">
    setget,access,remove,hasData,discard
  • 相关阅读:
    什么是95%的置信区间?
    机器学习博客
    深度自动编码器
    深度神经网络中的权重初始化方法
    自编码器和去噪自编码器的可视化
    08 scrapy框架
    redis.exceptions.DataError: Invalid input of type: 'dict'. Convert to a bytes, string, int or float first.
    Redis 教程
    selenium 滑动解锁(drag_and_drop_by_offset)
    获取登陆cookie,并且利用cookie访问登陆后的界面
  • 原文地址:https://www.cnblogs.com/aaron911/p/9717409.html
Copyright © 2011-2022 走看看