• jQuery源码分析之=>jQuery的定义


    最近写前段的代码比较多,jQuery是用的最多的一个对象,但是之前几次看了源码,都没搞清楚jQuery是怎么定义的,今天终于看明白怎么回事了。记录下来,算是一个新的开始吧。

    (文中源码都是jQuery-1.10.2版本的)

    先上一段jQuery定义的源码,定义了jQuery为一个function

    1     // Define a local copy of jQuery
    2     jQuery = function( selector, context ) {
    3         // The jQuery object is actually just the init constructor       'enhanced'
    4         return new jQuery.fn.init( selector, context, rootjQuery );
    5     } 

    这就是我们常用的格式:$("#div1");就是通过这个函数定义的

    这个函数只有一行有效代码,就是实例化了一个类型,这个类型是在jQuery的原型中定义的,那么继续往下看。

      1 jQuery.fn = jQuery.prototype = {
      2     // The current version of jQuery being used
      3     jquery: core_version,
      4 
      5     constructor: jQuery,
      6     init: function( selector, context, rootjQuery ) {
      7         var match, elem;
      8 
      9         // HANDLE: $(""), $(null), $(undefined), $(false)
     10         if ( !selector ) {
     11             return this;
     12         }
     13 
     14         // Handle HTML strings
     15         if ( typeof selector === "string" ) {
     16             if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
     17                 // Assume that strings that start and end with <> are HTML and skip the regex check
     18                 match = [ null, selector, null ];
     19 
     20             } else {
     21                 match = rquickExpr.exec( selector );
     22             }
     23 
     24             // Match html or make sure no context is specified for #id
     25             if ( match && (match[1] || !context) ) {
     26 
     27                 // HANDLE: $(html) -> $(array)
     28                 if ( match[1] ) {
     29                     context = context instanceof jQuery ? context[0] : context;
     30 
     31                     // scripts is true for back-compat
     32                     jQuery.merge( this, jQuery.parseHTML(
     33                         match[1],
     34                         context && context.nodeType ? context.ownerDocument || context : document,
     35                         true
     36                     ) );
     37 
     38                     // HANDLE: $(html, props)
     39                     if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
     40                         for ( match in context ) {
     41                             // Properties of context are called as methods if possible
     42                             if ( jQuery.isFunction( this[ match ] ) ) {
     43                                 this[ match ]( context[ match ] );
     44 
     45                             // ...and otherwise set as attributes
     46                             } else {
     47                                 this.attr( match, context[ match ] );
     48                             }
     49                         }
     50                     }
     51 
     52                     return this;
     53 
     54                 // HANDLE: $(#id)
     55                 } else {
     56                     elem = document.getElementById( match[2] );
     57 
     58                     // Check parentNode to catch when Blackberry 4.6 returns
     59                     // nodes that are no longer in the document #6963
     60                     if ( elem && elem.parentNode ) {
     61                         // Handle the case where IE and Opera return items
     62                         // by name instead of ID
     63                         if ( elem.id !== match[2] ) {
     64                             return rootjQuery.find( selector );
     65                         }
     66 
     67                         // Otherwise, we inject the element directly into the jQuery object
     68                         this.length = 1;
     69                         this[0] = elem;
     70                     }
     71 
     72                     this.context = document;
     73                     this.selector = selector;
     74                     return this;
     75                 }
     76 
     77             // HANDLE: $(expr, $(...))
     78             } else if ( !context || context.jquery ) {
     79                 return ( context || rootjQuery ).find( selector );
     80 
     81             // HANDLE: $(expr, context)
     82             // (which is just equivalent to: $(context).find(expr)
     83             } else {
     84                 return this.constructor( context ).find( selector );
     85             }
     86 
     87         // HANDLE: $(DOMElement)
     88         } else if ( selector.nodeType ) {
     89             this.context = this[0] = selector;
     90             this.length = 1;
     91             return this;
     92 
     93         // HANDLE: $(function)
     94         // Shortcut for document ready
     95         } else if ( jQuery.isFunction( selector ) ) {
     96             return rootjQuery.ready( selector );
     97         }
     98 
     99         if ( selector.selector !== undefined ) {
    100             this.selector = selector.selector;
    101             this.context = selector.context;
    102         }
    103 
    104         return jQuery.makeArray( selector, this );
    105     },
    106         。。。其他方法省略
    107 }

    在上面这段代码中,定义了jQuery的原型,然后将原型赋给了jQuery.fn;$.fn这个东西大家应该都很熟悉了,我们扩展jQuery插件的时候时长用到它,其实就是想jQuery的原型中添加了方法。

    在原型的定义中重要的就是init函数了,有三个参数:selector,context,rootjQuery。

    在这个函数中根据各种情况做了判断,比如:selector对象为false时的就是处理$("")或者$(null)或者$(undefined),(注释上都有说明);

    如果selector是function时,就是我们最常用的页面加载处理函数:$(function(){......});

    到这里,应该就可以明白了,jQuery对象不过是一个函数,然后在内部实例化了一个jQuery.fn.init;

    但是问题来了,我们做jQuery插件的时候,扩展的是jQuery.fn,是jQuery的原型,跟jQuery.fn.init的实例化对象没有关系,这是怎么回事?

    接下来这行代码就解决了我的疑惑:

    1 // Give the init function the jQuery prototype for later instantiation
    2 jQuery.fn.init.prototype = jQuery.fn;

    将jQuery原型的定义赋给了jQuery.fn.init的原型,这样我们在扩展jQuery原型的同时,也扩展了jQuery.fn.init的原型,那么jQuery对象就有了那些方法(确切的说应该是jQuery.fn.init类型的实例化对象)

    接下来的源码定义了jQuery.extend=jQuery.fn.extend=function(){};然后通过这两个方法添加了预定义的方法和属性,比如:ready函数、isFunction函数、each函数等等

    到这里差不多jQuery的定义就结束了,我们常用的一些方法也在源代码中通过extend方法预先定义好了。

  • 相关阅读:
    解决前端从url路径上拿到的中文乱码
    仪表盘双层结构图
    element ui 按钮显示
    vue在手机上运行,打包之后显示
    echarts使用遇到的一些问题总结,比如颜色改变,文字位置调整
    微信小程序地图移动到指定的位置
    微信小程序多边形地图显示
    button取消边框
    代码审计小记 (一)
    [root-me](web-client)write up 一个大坑怎么填啊
  • 原文地址:https://www.cnblogs.com/chengzi/p/4269317.html
Copyright © 2020-2023  润新知