jQuery 源码分析(二) 入口模块
jQuery返回的对象本质上是一个JavaScript对象,而入口模块则可以保存对应的节点的引用,然后供其它模块操作
我们创建jQuery对象时可以给jQuery传递各种不同的选择器,如下:
false ;返回一个空jQuery对象
DOM节点 ;返回包含该DOM元素引用的jQuery对象。
body ;字符串'body',返回包含body元素引用的jQuery对象
单独标签 ;调用document.createElement创建标签对应的DOM元素
较复杂的html代码 ;调用jQuery.buildFragment创建元素
函数 ;是$(document).ready(function)的简写,等到DOM加载完毕后再执行,后面有几篇专门介绍
例如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script>
</head>
<body>
<p id="p">123</p>
<script>
console.log( $(false) )
console.log( $(p) )
console.log( $('body') )
console.log( $('<p>123</p>') )
$(function(){console.log('Dom loaded')})
</script>
</body>
</html>
输出如下:

输出的五条信息分别对应上面的五个输出,第一条为空jQuery对象,第二条为包含p元素的jQuery对象,第三条为包含body节点引用的jQuery对象,第四条为jQuery创建的未挂载到dom的jQuery对象,第五条就直接输出信息的,对应着例子的$(function(){})对象
源码分析
writer by:大沙漠 QQ:22969969
入口模块就是上一篇文章分析的jQuery内部的jQuery.fn.init函数,该函数会通过参数的不同来做不同的实现,如下:
init: function( selector, context, rootjQuery ) { //负责解析参数selector和context的类型,并执行相应的逻辑
var match, elem, ret, doc;
// Handle $(""), $(null), or $(undefined)
if ( !selector ) { //selector是"",null,undefined和false的等可以转换为false的情况下,对应上面的第一个jQuery实例
return this;
}
// Handle $(DOMElement)
if ( selector.nodeType ) { //selector有属性nodeType,则认为selector是DOM元素,例如:$(document.getELementById('d')),对应上面的第二个jQuery实例
this.context = this[0] = selector;
this.length = 1;
return this;
}
// The body element only exists once, optimize finding it
if ( selector === "body" && !context && document.body ) { //如果参数selector是字符串'body',且context为空,如:$('body'),对应上面的第三个jQuery实例
this.context = document;
this[0] = document.body;
this.selector = selector;
this.length = 1;
return this;
}
// Handle HTML strings
if ( typeof selector === "string" ) { //参数selector是字符串形式
// Are we dealing with HTML string or an ID?
if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { //如果参数selector以"<"开头、以">"结尾,且长度大于等于3
// Assume that strings that start and end with <> are HTML and skip the regex check
match = [ null, selector, null ]; //则假设这个字符串是HTML片段,跳过正则quickExpr的检查。注意这里仅仅是假设,并不一定表示它是真正合法的HTML代码
} else {
match = quickExpr.exec( selector ); //否则用quickExpr来检测参数selector是否为稍微复杂一点的代码,
}
// Verify a match, and that no context was specified for #id
if ( match && (match[1] || !context) ) {
// HANDLE: $(html) -> $(array)
if ( match[1] ) {
context = context instanceof jQuery ? context[0] : context;
doc = ( context ? context.ownerDocument || context : document );
// If a single string is passed in and it's a single tag
// just do a createElement and skip the rest
ret = rsingleTag.exec( selector );
if ( ret ) { //如果参数selector是单独标签比如$('<p></p>');
if ( jQuery.isPlainObject( context ) ) {
selector = [ document.createElement( ret[1] ) ];
jQuery.fn.attr.call( selector, context, true );
} else {
selector = [ doc.createElement( ret[1] ) ];
}
} else {
ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
}
return jQuery.merge( this, selector );
// HANDLE: $("#id")
} else { //参数selector是"#id"格式,如:$('#p1')
elem = document.getElementById( match[2] );
// Check parentNode to catch when Blackberry 4.6 returns
// nodes that are no longer in the document #6963
if ( elem && elem.parentNode ) {
// Handle the case where IE and Opera return items
// by name instead of ID
if ( elem.id !== match[2] ) {
return rootjQuery.find( selector );
}
// Otherwise, we inject the element directly into the jQuery object
this.length = 1;
this[0] = elem;
}
this.context = document;
this.selector = selector;
return this;
}
// HANDLE: $(expr, $(...))
} else if ( !context || context.jquery ) {
return ( context || rootjQuery ).find( selector );
// HANDLE: $(expr, context)
// (which is just equivalent to: $(context).find(expr)
} else {
return this.constructor( context ).find( selector );
}
// HANDLE: $(function)
// Shortcut for document ready
} else if ( jQuery.isFunction( selector ) ) { //如果参数selector是函数,则认为是绑定ready事件,从这里可以看出$(function) 是$(document).ready(function)的简写,这里对应上面的第五个jQuery实例
return rootjQuery.ready( selector );
}
if ( selector.selector !== undefined ) {
this.selector = selector.selector;
this.context = selector.context;
}
return jQuery.makeArray( selector, this );
},
这样jQuery实例就获取到了对应的DOM节点的引用,之后就可以用底层模块或功能模块进行操作了。
jQuery 源码分析(二) 入口模块的更多相关文章
- jQuery 源码分析(二十一) DOM操作模块 删除元素 详解
本节说一下DOM操作模块里的删除元素模块,该模块用于删除DOM里的某个节点,也可以理解为将该节点从DOM树中卸载掉,如果该节点有绑定事件,我们可以选择保留或删除这些事件,删除元素的接口有如下三个: e ...
- jQuery 源码分析(二十) DOM操作模块 插入元素 详解
jQuery的DOM操作模块封装了DOM模型的insertBefore().appendChild().removeChild().cloneNode().replaceChild()等原生方法.分为 ...
- jquery源码分析(二)——架构设计
要学习一个库首先的理清它整体架构: 1.jQuery源码大致架构如下:(基于 jQuery 1.11 版本,共计8829行源码)(21,94) 定义了一些变量和函数jQu ...
- jQuery 源码分析(十一) 队列模块 Queue详解
队列是常用的数据结构之一,只允许在表的前端(队头)进行删除操作(出队),在表的后端(队尾)进行插入操作(入队).特点是先进先出,最先插入的元素最先被删除. 在jQuery内部,队列模块为动画模块提供基 ...
- jQuery 源码分析(十七) 事件系统模块 实例方法和便捷方法 详解
实例方法和便捷方法是指jQuery可以直接通过链接操作的方法,是通过调用$.event上的方法(上一节介绍的底层方法)来实现的,常用的如下: on(types,selector,data,fn,one ...
- jquery源码分析(七)——事件模块 event(二)
上一章节探讨了事件的一些概念,接下来看下jQuery的事件模块. jQuery对事件的绑定分别有几个API:.bind()/.live()/.delegate()/.on()/click(), 不管是 ...
- [Abp 源码分析]二、模块系统
0.简介 整个 Abp 框架由各个模块组成,基本上可以看做一个程序集一个模块,不排除一个程序集有多个模块的可能性.可以看看他官方的这些扩展库: 可以看到每个项目文件下面都会有一个 xxxModule ...
- 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入
使用react全家桶制作博客后台管理系统 前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...
- jQuery源码分析系列
声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...
随机推荐
- C# 如何添加自定义键盘处理事件 如何配置app.config ? | csharp key press event tutorial and app.config
本文首发于个人博客https://kezunlin.me/post/9f24ebb5/,欢迎阅读最新内容! csharp key press event tutorial and app.config ...
- 基础面试,为什么面试官总喜欢问String?
关于 Java String,这是面试的基础,但是还有很多童鞋不能说清楚,所以本文将简单而又透彻的说明一下那个让你迷惑的 String 在 Java 中,我们有两种方式创建一个字符串 String x ...
- 定位表和索引使用的Page
数据存储的基本单元是Page,每个Page是8KB,数据文件(mdf和ndf)占用的硬盘空间,逻辑上按照PageNumber进行划分,也就是说,可以把数据文件看作是PageNumber 从0到n的连续 ...
- 如何在GibHub上传自己的项目
如何上传项目至GinHub 准备好项目.在项目ssm-crud的目录下右击,点击Git Bash Here,打开git命令行. 在命令行中,输入git init,使项目文件夹加入git管理: 输入gi ...
- java基础(18):集合、Iterator迭代器、增强for循环、泛型
1. 集合 1.1 集合介绍 集合,集合是java中提供的一种容器,可以用来存储多个数据. 在前面的学习中,我们知道数据多了,可以使用数组存放或者使用ArrayList集合进行存放数据.那么,集合和数 ...
- JavaScript HTML DOM Style flexWrap 属性
flexWrap 属性 flexWrap属性指定flex项是否应该换行. 注意:如果元素不是flex项,则flexWrap属性不起作用. 如果必要,使flex换行: document.getEleme ...
- 【Gradle】Gradle构建脚本基础
Gradle构建脚本基础 Settings文件 在Gradle中,定义了一个设置文件,用于初始化以及工程树的配置.设置文件的默认名为settings.gradle,放在根工程目录下. 设置文件大多数的 ...
- 3. 海思Hi3519A MPP从入门到精通(三 视频输入)
视频输入(VI)模块实现的功能:通过 MIPI Rx(含 MIPI 接口.LVDS 接口和 HISPI 接 口),SLVS-EC,BT.1120,BT.656,BT.601,DC 等接口接收视频数据. ...
- 2019 Multi-University Training Contest 1 E Path(最短路+最小割)
题意 链接:https://vjudge.net/problem/HDU-6582 给定一个有向图,可以有重边,每条边上有一个权值表示删掉这条边的代价,问最少花费多少代价能使从s到t节点的最短路径增大 ...
- v-bind是是否需要绑定某一个类名
v-bind 结合 css样式 结合标签显示是否要显示出某个样式 <p :class="['bg','dx', {'lin':falg}]">{{ msg }}< ...