jQuery.prototype.init选择器构造函数源码思路分析


Posted in Javascript onFebruary 05, 2013

一、源码思路分析总结
概要:
jQuery的核心思想可以简单概括为“查询和操作dom”,今天主要是分析一下jQuery.prototype.init选择器构造函数,处理选择器函数中的参数;
这个函数的参数就是jQuery()===$()执行函数中的参数,可以先看我之前写的浅析jQuery基础框架一文,了解基础框架后,再看此文。
思路分析:
以下是几种jQuery的使用情况(用于查询dom),每种情况都返回一个选择器实例(习惯称jQuery对象(一个nodeList对象),该对象包含查询的dom节点):
1、处理 $(""), $(null), $(undefined), $(false)
如果参数为以上非法值,jQuery对象不包含dom节点
2、处理 $(DOMElement)
如果参数为节点元素,jQuery对象包含该参数节点元素,并分别增加属性值为参数节点元素、1的context、length属性和用[]访问jQuery对象中dom节点的用法
例2.1:

var obj = document.getElementById('container'), 
jq = $(obj); console.log(jq.length); //1 
console.log(jq.context); //obj 
console.log(jq.[0]); //obj

3、处理$(HTML字符串)
如果第一个参数为HTML字符串,jQuery对象包含由jQuery.clean函数创建的fragment文档碎片中的childnodes节点
例3.1:
var jqHTML = $('<h1>文章标题</h1><p>内容</p>'); 
console.log(jqHTML); //[<h1>,<p>];

如果第一个参数(HTML字符串)为一个空的单标签,且第二个参数context为一个非空纯对象
例3.2:
var jqHTML = $('<div></div>', { class: 'css-class', data-name: 'data-val' }); console.log(jqHTML.attr['class']); //css-class 
console.log(jqHTML.attr['data-name']); //data-val

4、处理$(#id)
如果第一个参数是一个#加元素id,jQuery对象包含唯一拥有该id的元素节点,
并分别增加属性值为document、参数字符串、1、的context、selector、length属性和用[]访问jQuery对象中dom节点的用法
例4.1:
var jq = $('#container'); console.log(jq.[0]); //包含的dom节点元素 
console.log(jq.length); //1 
console.log(jq.context); //document 
console.log(jq.selector); //container

5、处理$(.className)
如果第一个参数是一个.className,jQuery对象中拥有class名为className的标签元素,并增加一个属性值为参数字符串、document的selector、context属性
实际执行代码为:
return jQuery(document).find(className);

6、处理$(.className, context)
如果第一个参数是.className,第二个参数是一个上下文对象(可以是.className(等同于处理$(.className .className)),jQuery对象或dom节点),
jQuery对象包含第二个参数上下文对象中拥有class名为className的后代节点元素,并增加一个context和selector属性
实际执行代码为:
return jQuery(context).find(className);

例6.1:
html代码:
<div class="main"> 
<h2 class="title">主内容标题</h2> 
<p>主标题</p> 
</div> 
<div class="sub"> 
<h2 class="title">次内容标题</h2> 
<p>次标题</p> 
</div>

JavaScript代码:
var jq, context; 
context = '.sub'; 
var jq = $('.title', context); 
console.log(jq.text()); //次内容标题 
console.log(jq.context); //document 
console.log(jq.selector); //.sub .title 
context = $('.sub'); 
var jq = $('.title', context); 
console.log(jq.text()); //次内容标题 
console.log(jq.context); //document 
console.log(jq.selector); //.sub .title 
context = $('.sub')[0]; 
var jq = $('.title', context); 
console.log(jq.text()); //次内容标题 
console.log(jq.context); //className为sub的节点元素 
console.log(jq.selector); //.title

7、处理$(fn)
如果第一个参数是fn函数,则调用$(document).ready(fn);
例7.1:
$(function(e){ 
console.log('DOMContent is loaded'); 
}) 
//上面代码等同于: 
jQuery(document).ready(function(e) { 
console.log('DOMContent is loaded'); 
});

8、处理$(jQuery对象)
如果第一个参数是jQuery对象,上面已经分析过如果在查询dom时,参数是一个#加元素id,返回的jQuery对象会增加一个属性值为参数字符串、document的selector、context属性
例8.1:
var jq = $('#container'); 
console.log(jq.selector); // #container 
console.log(jq.context); // document

那么当出现$($('#container'))该如何处理呢?同样的,返回的jQuery对象同情况5和6处理的情况一样
例8.2:
var jq2 = $($('#container')); 
console.log(jq2.selector); // #container 
console.log(jq2.context); // document

二、源码注释分析
[ 基于jQuery1.8.3 ]
var rootjQuery = $(document), 
rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/; 
jQuery.fn = jQuery.prototype = { 
init: function( selector, context, rootjQuery ) { 
var match, elem, ret, doc; 
// Handle $(""), $(null), $(undefined), $(false) 
if ( !selector ) { 
return this; 
} 
// Handle $(DOMElement) 
if ( selector.nodeType ) { 
this.context = this[0] = selector; 
this.length = 1; 
return this; 
} 
// Handle HTML strings 
if ( typeof selector === "string" ) { 
if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { 
// Assume that strings that start and end with <> are HTML and skip the regex check 
match = [ null, selector, null ]; 
} else { 
match = rquickExpr.exec( selector ); 
} 
// Match html or make sure no context is specified for #id 
// match[1]不为null,则为html字符串,match[2]不为null,则为元素id 
if ( match && (match[1] || !context) ) { 
// HANDLE: $(html) -> $(array) 
if ( match[1] ) { 
context = context instanceof jQuery ? context[0] : context; 
doc = ( context && context.nodeType ? context.ownerDocument || context : document ); 
// scripts is true for back-compat 
// selector是由文档碎片中的childnodes组成的数组 
selector = jQuery.parseHTML( match[1], doc, true ); 
// 如果match[1]为空的单标签元素(如:<div><div>)且context为对象字面量 
if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { 
// 如果context对象不为空,则将对象中的属性添加到selector数组中仅有的dom节点中 
this.attr.call( selector, context, true ); 
} 
// merge函数的参数应该为两个数组,目的是将第二个数组中的项合并到第一个数组,而this并不是一个数组, 
// this是选择器init构造函数的实例对象,该对象继承jQuery.prototype对象中的length属性(默认为0),因此可以理解好merge函数源码 
// 将selector中的dom项合并到this对象中,并返回该对象 
return jQuery.merge( this, selector ); 
// HANDLE: $(#id) 
} else { 
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 
// ie6,7和Opera存在此bug,当一个标签name和一个标签id值相等时, 
// document.getElementById(#id)函数将返回提前出现的标签元素 
if ( elem.id !== match[2] ) { 
// 如果存在以上Bug,则返回由find函数返回的document文档的后代元素集合 
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, $(...)) 
// context不存在或者context为jQuery对象 
} else if ( !context || context.jquery ) { 
return ( context || rootjQuery ).find( selector ); 
// HANDLE: $(expr, context) 
// (which is just equivalent to: $(context).find(expr) 
// context为className或者dom节点元素 
} else { 
// 等同于jQuery(context).find(selector) 
return this.constructor( context ).find( selector ); 
} 
// 处理$(fn)===$(document).ready(fn) 
} else if ( jQuery.isFunction( selector ) ) { 
return rootjQuery.ready( selector ); 
} 
// 处理$(jQuery对象) 
if ( selector.selector !== undefined ) { 
this.selector = selector.selector; 
this.context = selector.context; 
} 
// 当第一个参数selector为jQuery对象时,将selector中的dom节点合并到this对象中,并返回this对象 
return jQuery.makeArray( selector, this ); 
} 
}
Javascript 相关文章推荐
基本jquery的控制tabs打开的数量的代码
Oct 17 Javascript
javascript scrollTop正解使用方法
Nov 14 Javascript
JavaScript 事件对象介绍
Apr 13 Javascript
浅谈bootstrap使用中的一些问题以及解决过程
Oct 18 Javascript
JS实现定时任务每隔N秒请求后台setInterval定时和ajax请求问题
Oct 15 Javascript
基于vue-cli配置lib-flexible + rem实现移动端自适应
Dec 26 Javascript
Express进阶之log4js实用入门指南
Feb 10 Javascript
Bootstrap Table中的多选框删除功能
Jul 15 Javascript
详解bootstrap-fileinput文件上传控件的亲身实践
Mar 21 Javascript
laydate只显示时分 不显示秒的功能实现方法
Sep 28 Javascript
详解微信小程序之提高应用速度小技巧
Jan 07 Javascript
vue项目或网页上实现文字转换成语音播放功能
Jun 09 Javascript
jQuery不间断滚动效果(模拟百度新闻支持文字/图片/垂直滚动)
Feb 05 #Javascript
得到jQuery detach()后节点中的某个值实现代码
Feb 05 #Javascript
jquery zTree异步加载简单实例分享
Feb 05 #Javascript
JS打印gridview实现原理及代码
Feb 05 #Javascript
漂亮的jquery提示效果(仿腾讯弹出层)
Feb 05 #Javascript
Js 获取Gridview选中行的内容操作步骤
Feb 05 #Javascript
6款经典实用的jQuery小插件及源码(对话框/提示工具等等)
Feb 04 #Javascript
You might like
不用GD库生成当前时间的PNG格式图象的程序
2006/10/09 PHP
php使用正则表达式进行字符串搜索的方法
2015/03/23 PHP
jquery isEmptyObject判断是否为空对象的函数
2011/02/14 Javascript
jquery聚焦文本框与扩展文本框聚焦方法
2012/10/12 Javascript
js渐变显示渐变消失示例代码
2013/08/01 Javascript
JQuery设置文本框和密码框得到焦点时的样式
2013/08/30 Javascript
js判读浏览器是否支持html5的canvas的代码
2013/11/18 Javascript
模拟一个类似百度google的模糊搜索下拉列表
2014/04/15 Javascript
jQuery将所有被选中的checkbox某个属性值连接成字符串的方法
2015/01/24 Javascript
如何实现chrome浏览器关闭页面时弹出“确定要离开此面吗?”
2015/03/05 Javascript
js实现交换运动效果的方法
2015/04/10 Javascript
js移动焦点到最后位置的简单方法
2016/11/25 Javascript
smartupload实现文件上传时获取表单数据(推荐)
2016/12/12 Javascript
详解vue2.0脚手架的webpack 配置文件分析
2017/05/27 Javascript
Vue中img的src是动态渲染时不显示的解决
2019/11/14 Javascript
javascript中的offsetWidth、clientWidth、innerWidth及相关属性方法
2020/05/14 Javascript
JavaScript实现沿五角星形线摆动的小圆实例详解
2020/07/28 Javascript
Python实现删除列表中满足一定条件的元素示例
2017/06/12 Python
Python正则捕获操作示例
2017/08/19 Python
Scrapy框架爬取西刺代理网免费高匿代理的实现代码
2019/02/22 Python
PyQt5的PyQtGraph实践系列3之实时数据更新绘制图形
2019/05/13 Python
详解Python列表赋值复制深拷贝及5种浅拷贝
2019/05/15 Python
使用Python的datetime库处理时间(RPA流程)
2019/11/24 Python
python如何使用jt400.jar包代码实例
2019/12/20 Python
Python3.7黑帽编程之病毒篇(基础篇)
2020/02/04 Python
python 3.8.3 安装配置图文教程
2020/05/21 Python
历史学专业推荐信
2013/11/06 职场文书
运动会100米解说词
2014/01/23 职场文书
计算机毕业生自荐信范文
2014/03/23 职场文书
《路旁的橡树》教学反思
2014/04/07 职场文书
新党章的学习心得体会
2014/11/07 职场文书
初中成绩单评语
2014/12/29 职场文书
2015年端午节活动总结
2015/02/11 职场文书
安全教育培训心得体会
2016/01/15 职场文书
干货:企业内部人才推荐奖励方案!
2019/07/09 职场文书
7个关于Python的经典基础案例
2021/11/07 Python