• jQuery 源码分析2: jQuery.fn.init


      1 //jQuery.fn.intit 中使用到的外部变量:
      2 
      3 // 判断是否为HTML标签或#id
      4 rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/;
      5 
      6 // window.document的jQuery对象
      7 rootjQuery = jQuery(window.document);
      8 
      9 // 判断是否为HTML标签
     10 rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
     11 
     12 init = jQuery.fn.init = function( selector, context ) {
     13           var match, elem;
     14 
     15           // 处理空selector $(""), $(null), $(undefined), $(false)
     16           if ( !selector ) {
     17                return this;          // 返回空jQuery对象
     18           }
     19           // 处理 HTML 字符串
     20           if ( typeof selector === "string" ) {
     21                if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
     22                     // 如果头尾含有 "<", ">"则跳过正则表达式检查
     23                     match = [ null, selector, null ];
     24                } else {
     25                     match = rquickExpr.exec( selector );     // 使用正则表达式检查是否为#id或HTML标签
     26                }
     27                // 确定是一个html标签,或为#id时没有特定的上下文
     28                if ( match && (match[1] || !context) ) {
     29                      // HANDLE: $(html) -> $(array)
     30                     if ( match[1] ) {
     31                          context = context instanceof jQuery ? context[0] : context;
     32                          // jQuery.merge把jQuery.parseHTML的返回值合并到this上
     33                          // jQuery.parseHTML将HTML字符串转换为一个DOM节点的集合
     34                          // 如果context不为空则以conext节点为上下文来创建HTML片段
     35                          // jQuery.parseHTML中的参数true表明保留HTML字符串中的脚本
     36                          // 如果parseHTML方法不存在则会抛出异常
     37                          jQuery.merge( this, jQuery.parseHTML(
     38                               match[1],
     39                               context && context.nodeType ? context.ownerDocument || context : document,
     40                               true
     41                          ) );
     42                           // jQuery(html, attributes),example
     43                          // $( "<div></div>", {
     44                          //      "class": "my-div",
     45                          //      on: { touchstart: function( event ) {// Do something}
     46                          // }
     47                          // })
     48                          // rsingleTag检测字符串时候为一个HTML tag
     49                          // jQuery.isPlainObject 判断context是否为纯粹的对象字面量
     50                          // 纯粹对象字面量表明这个对象是有new或{}创建的,它有构造器,有原型链继承,但要排除window或DOM对象
     51 
     52                          // 如果context不是纯粹对象字面量,for in 语句操作可能会出错
     53                          if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
     54                               for ( match in context ) {
     55                                    // 调用自身的方法
     56                                    if ( jQuery.isFunction( this[ match ] ) ) {
     57                                         this[ match ]( context[ match ] );
     58                                     // 设置属性
     59                                    } else {
     60                                         this.attr( match, context[ match ] );
     61                                    }
     62                               }
     63                          }
     64                           return this;
     65                      // $('#id') 选择id
     66                     } else {
     67 
     68                          // 直接利用document的方法来说实现
     69                          elem = document.getElementById( match[2] );
     70                           // Check parentNode to catch when Blackberry 4.6 returns
     71                          // nodes that are no longer in the document #6963
     72                          // Blackberry4.6 返回时有parentNode
     73                          if ( elem && elem.parentNode ) {
     74 
     75                               // IE和Opera的返回对象是第一个name符合的对象
     76                               if ( elem.id !== match[2] ) {     // 如果ID错误,在rootjQuery中用find查找
     77                                    return rootjQuery.find( selector );
     78                               }
     79                                // 如果不存在这个节点,则插入一个
     80                               this.length = 1;
     81                               this[0] = elem;
     82                          }
     83                           this.context = document;     // 添加上下文
     84                          this.selector = selector;    // 更改选择器为id
     85                          return this;
     86                     }
     87                 // 选择器表达式: $(expr, $(...))
     88 
     89                // 如果context为空或context是一个jQuery对象,jQuery.jquery存放version信息
     90                } else if ( !context || context.jquery ) {
     91                     return ( context || rootjQuery ).find( selector );
     92                 // 选择器表达式: $(expr, context)
     93                // 等同于: $(context).find(expr)
     94                } else {        // 利用jQuery构造器调用context
     95                     return this.constructor( context ).find( selector );
     96                }
     97            // $(a_node), 一个DOM节点元素
     98           } else if ( selector.nodeType ) {     // 直接把该节点添加到this上
     99                this.context = this[0] = selector;
    100                this.length = 1;
    101                return this;
    102            // selector 是一个function, 调用jQuery.ready(func) 的快捷方式
    103           } else if ( jQuery.isFunction( selector ) ) {
    104                return typeof rootjQuery.ready !== "undefined" ?
    105                     rootjQuery.ready( selector ) :
    106                     // 如果ready方法不存在,则立即执行
    107                     selector( jQuery );
    108           }
    109            if ( selector.selector !== undefined ) {     // 如果选择器包含其他属性,赋值给this的同名属性
    110                this.selector = selector.selector;
    111                this.context = selector.context;
    112           }
    113           
    114 
    115           // 将selector合并到this上
    116           return jQuery.makeArray( selector, this );
    117      };
     
     
     
         init执行过程:
    • 处理空selector,相当于返回jQuery方法接口
    • 判断HTML字符串
      • HTML字符或#id
        • 单独HTML标签,创建DOM对象并插入
        • #id,使用document.getElementById获取DOM对象
      • 选择器表达式,使用$.find
    • 函数,注册到ready或立即执行
    • DOM对象,直接返回
     
    可以看到init初始化一个jQuery对象,根据形参来搜索或建立一个DOM对象(又或者是执行jQuery.ready方法),并将该对象返回。
    jQuery.fn.init的实现十分精明,在JavaScript中实现了方法的重载,让API调用变得更为简单方便。
    过程中有针对浏览器兼容性的处理、纯粹对象判断,用来保证运行的可靠性和稳定性,这部分十分值得研读和学习。


  • 相关阅读:
    Drupal 学习笔记 (4)
    property和field有什么区别
    Razor4Orchard v1.2
    Mono喜迁新家http://www.xamarin.com/
    jq中获取属性名的方法
    jquery中的文档操作之五
    PHP基础知识之三
    php基础知识之一
    注意点
    jquery中ajax的学习之$.ajax()
  • 原文地址:https://www.cnblogs.com/elcarim5efil/p/4668544.html
Copyright © 2020-2023  润新知