//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. Win+R指令(2)

    1. gpedit.msc-----组策略 2. sndrec32-------录音机 3. Nslookup-------IP地址侦测器 ,是一个 监测网络中 DNS 服务器是否能正确实现域名解析的 ...

  2. jquery中链式操作的this指向

    jquery中链式操作是如何实现? 例如:$(obj).children().css('color','red').next().css('color','red').siblings().css(' ...

  3. 订阅基础:RSS、ATOM、FEED、聚合、供稿、合烧与订阅

    很多网友对这类名词概念非常陌生,如果没用过FEED订阅,肯定还会对诸多网站显示的FEED聚合.订阅.ATOM等等非常郁闷,虽然这几个名字间的很多并非并列关系,天缘只是有意把它们放到一起,方便对比参考, ...

  4. CAS 之 集成RESTful API

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  5. DDD的好文章

    http://www.jdon.com/44815   //cqrs 架构 http://www.jdon.com/tags/272 解道领域驱动专题

  6. crm操作权限

    using System;     using Microsoft.Xrm.Sdk;     using Microsoft.Xrm.Sdk.Query;     using System.Colle ...

  7. 【Servlet】Filter过滤器的编写和配置

    Servlet的Filter介绍 在Servlet作为过滤器使用时,它可以对客户的请求进行过滤处理,当它处理完成后,它会交给下一个过滤器处理,就这样,客户的请求在过滤链里一个个处理,直到请求发送到目标 ...

  8. Java出现No enclosing instance of type E is accessible. Must qualify the allocation with an enclosing--转

    原文:http://blog.csdn.net/sunny2038/article/details/6926079 最近在看Java,在编译写书上一个例子时,由于书上的代码只有一部分,于是就自己补了一 ...

  9. Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解(四)

    这一章大象将详细分析web层代码,以及使用Spring MVC的注解及其用法和其它相关知识来实现控制器功能.     之前在使用Struts2实现MVC的注解时,是借助struts2-conventi ...

  10. AIDL通信原理

    AIDL (Android Interface Definition Language),通过定义通信接口来实现进程间通信.这是Google提供的一种在安卓应用进程间通信的工具.所以要了解AIDL的通 ...