//jQuery.fn.intit 中使用到的外部变量:

 // 判断是否为HTML标签或#id
rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/; // window.document的jQuery对象
rootjQuery = jQuery(window.document); // 判断是否为HTML标签
rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); init = jQuery.fn.init = function( selector, context ) {
var match, elem; // 处理空selector $(""), $(null), $(undefined), $(false)
if ( !selector ) {
return this; // 返回空jQuery对象
}
// 处理 HTML 字符串
if ( typeof selector === "string" ) {
if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
// 如果头尾含有 "<", ">"则跳过正则表达式检查
match = [ null, selector, null ];
} else {
match = rquickExpr.exec( selector ); // 使用正则表达式检查是否为#id或HTML标签
}
// 确定是一个html标签,或为#id时没有特定的上下文
if ( match && (match[1] || !context) ) {
// HANDLE: $(html) -> $(array)
if ( match[1] ) {
context = context instanceof jQuery ? context[0] : context;
// jQuery.merge把jQuery.parseHTML的返回值合并到this上
// jQuery.parseHTML将HTML字符串转换为一个DOM节点的集合
// 如果context不为空则以conext节点为上下文来创建HTML片段
// jQuery.parseHTML中的参数true表明保留HTML字符串中的脚本
// 如果parseHTML方法不存在则会抛出异常
jQuery.merge( this, jQuery.parseHTML(
match[1],
context && context.nodeType ? context.ownerDocument || context : document,
true
) );
// jQuery(html, attributes),example
// $( "<div></div>", {
// "class": "my-div",
// on: { touchstart: function( event ) {// Do something}
// }
// })
// rsingleTag检测字符串时候为一个HTML tag
// jQuery.isPlainObject 判断context是否为纯粹的对象字面量
// 纯粹对象字面量表明这个对象是有new或{}创建的,它有构造器,有原型链继承,但要排除window或DOM对象 // 如果context不是纯粹对象字面量,for in 语句操作可能会出错
if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
for ( match in context ) {
// 调用自身的方法
if ( jQuery.isFunction( this[ match ] ) ) {
this[ match ]( context[ match ] );
// 设置属性
} else {
this.attr( match, context[ match ] );
}
}
}
return this;
// $('#id') 选择id
} else { // 直接利用document的方法来说实现
elem = document.getElementById( match[2] );
// Check parentNode to catch when Blackberry 4.6 returns
// nodes that are no longer in the document #6963
// Blackberry4.6 返回时有parentNode
if ( elem && elem.parentNode ) { // IE和Opera的返回对象是第一个name符合的对象
if ( elem.id !== match[2] ) { // 如果ID错误,在rootjQuery中用find查找
return rootjQuery.find( selector );
}
// 如果不存在这个节点,则插入一个
this.length = 1;
this[0] = elem;
}
this.context = document; // 添加上下文
this.selector = selector; // 更改选择器为id
return this;
}
// 选择器表达式: $(expr, $(...)) // 如果context为空或context是一个jQuery对象,jQuery.jquery存放version信息
} else if ( !context || context.jquery ) {
return ( context || rootjQuery ).find( selector );
// 选择器表达式: $(expr, context)
// 等同于: $(context).find(expr)
} else { // 利用jQuery构造器调用context
return this.constructor( context ).find( selector );
}
// $(a_node), 一个DOM节点元素
} else if ( selector.nodeType ) { // 直接把该节点添加到this上
this.context = this[0] = selector;
this.length = 1;
return this;
// selector 是一个function, 调用jQuery.ready(func) 的快捷方式
} else if ( jQuery.isFunction( selector ) ) {
return typeof rootjQuery.ready !== "undefined" ?
rootjQuery.ready( selector ) :
// 如果ready方法不存在,则立即执行
selector( jQuery );
}
if ( selector.selector !== undefined ) { // 如果选择器包含其他属性,赋值给this的同名属性
this.selector = selector.selector;
this.context = selector.context;
} // 将selector合并到this上
return jQuery.makeArray( selector, this );
};
 
 
 
     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调用变得更为简单方便。
过程中有针对浏览器兼容性的处理、纯粹对象判断,用来保证运行的可靠性和稳定性,这部分十分值得研读和学习。

jQuery 源码分析2: jQuery.fn.init的更多相关文章

  1. jQuery源码分析之=>jQuery的定义

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

  2. jQuery 源码分析3: jQuery.fn/ jQuery.prototype

    // 建立方法实例,提高方法访问的速度(避免在原型链上搜索) var deletedIds = []; var slice = deletedIds.slice; var concat = delet ...

  3. jQuery 源码分析4: jQuery.extend

    jQuery.extend是jQuery最重要的方法之一,下面看看jQuery是怎样实现扩展操作的 // 如果传入一个对象,这个对象的属性会被添加到jQuery对象中 // 如果传入两个或多个对象,所 ...

  4. 六.jQuery源码分析之jQuery原型属性和方法

    97 jQuery.fn = jQuery.prototype = { 98 constructor: jQuery, 99 init: function( selector, context, ro ...

  5. jQuery 源码分析6: jQuery 基本静态方法(二)

    jQuery.extend({ // 遍历obj的所有值 // args 这参数只能内部调用的会用到 // 注意到,如果回调函数调用失败会直接跳出并中止遍历 // 当有args数组时,使用apply调 ...

  6. jQuery 源码分析5: jQuery 基本静态方法(一)

    jQuery在初始化过程中会为自己扩展一些基本的静态方法和属性,以下是jQuery 1.11.3版本 239 ~ 564行间所扩展的静态属性和方法   jQuery.extend({ // 为每个jQ ...

  7. jQuery 源码分析 8: 回头看jQuery的构造器(jQuery.fn,jQury.prototype,jQuery.fn.init.prototype的分析)

    在第一篇jQuery源码分析中,简单分析了jQuery对象的构造过程,里面提到了jQuery.fn.jQuery.prototype.jQuery.fn.init.prototype的关系. 从代码中 ...

  8. Jquery源码分析-整体结构

    最近在学习Jquery的最新的源码,Jquery-3.3.1版本.网上有很多对jquery解析的文章.但是我还是要自己去尝试着看一篇jquery的源码.本系列博客用来记录其中的过程,并同大家分享.本次 ...

  9. jQuery源码分析系列

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...

随机推荐

  1. HDOJ-ACM1019(JAVA) 多个数的最小公倍数

    题意:求多个数的最小公倍数 很简单,但是我一开始的做法,估计会让结果越界(超过int的最大值) import java.util.*; import java.io.*; public class M ...

  2. Js/Jquery- Base64和UrlEncode编码解码

    最近几天遇到一些URL参数明文显示的问题,因为是明文显示,容易让人通过改变参数查看到他没有权限看到内容. 一开始我的做法是自定义了规则,然后原始的那种URL编码.可是URL编译后效果不理想,他无法编译 ...

  3. MSSQLSERVER数据库- 字符串分割函数返回类型表

    遇到这样一个问题,存储在数据库的数据是一串字符串如:1,2,3,4,5,6.想把这串字符串进行转变成一个表格,如下: 1 2 3 4 5 6 就是这样一个问题,有人同事,写了一个这样的封装函数,这样就 ...

  4. Maven管理项目架包

    最近一直在用Maven管理项目的架包,从而发现了几个不错的官方或者非官方的网站. http://mvnrepository.com/artifact/com.ning  这个是我刚刚用来找HTTP开发 ...

  5. 动态调用DLL函数有时正常,有时报Access violation的异常

    动态调用DLL函数有时正常,有时报Access violation的异常 typedef int (add *)(int a,int b); void test() {     hInst=LoadL ...

  6. git版本号管理工具的上手

    git是一个分布式的版本号管理工具 和其它集中式版本号管理 工具相比具有下面长处: 1.能够在不联网的情况下开发 2.能够方便的建立本地分支 3.本地化的日志,高速获得信息 git命令的使用 mkdi ...

  7. [React] React Fundamentals: First Component

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  8. Java 加密解密 对称加密算法 非对称加密算法 MD5 BASE64 AES RSA

    版权声明:本文为博主原创文章,未经博主允许不得转载. [前言] 本文简单的介绍了加密技术相关概念,最后总结了java中现有的加密技术以及使用方法和例子 [最简单的加密] 1.简单的概念 明文:加密前的 ...

  9. careercup-递归和动态规划 9.1

    9.1 有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶.2阶或3阶.实现一个方法,计算小孩有多少种上楼梯的方法. 解法: 我们可以采用自上而下的方式来解决这个问题.小孩上楼梯的最后一步,也就是 ...

  10. Android(java)学习笔记143:android提供打开各种文件的API接口:setDataAndType

    android 打开各种文件(setDataAndType) private void openFile(File file){ Intent intent = new Intent(); inten ...