标签:并且 match har ons ase 理解 image gre pac
上一篇jQuery分析(2)中了解了jQuery库的骨架实现原理,这就好比摇滚音乐,摇滚音乐不是某种音乐他就像一个音乐盒子,里面包含了各种不同的摇滚风格(山地、朋克、乡村、流行、硬摇、金属、迷幻等)。那么上一篇只是大致了解了jQuery的基本形状,从这篇文章开始会深入jQuery库的各种函数,深入详细的去了解他,那将值得慢慢探索,发现新的神奇好玩的东西。
在jQuery.fn.init方法里面使用到了一些jQuery的静态函数,在这里提前统一的介绍
下面图是jQeury的构造函数参数即$()调用的参数种类集合图
下面的代码是可能处理各种参数的方式,多余的代码我已删除掉,下面代码清晰看到selector无非就是三种类型:1、字符串 2、DOMElement 3、函数。下面将会就这三种类型进行详细深入的分析他们的实现原理,这将需要一步一步来理解,首先脑子里要清晰每一步做了什么为什么这样做,这样一步一步下来才能更好的去理解jQuery的写法。
// 匹配html标签写法和id选择器
// 第一个分组是 <div> 中的div,第二个分组是#id中的id
rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
jQuery.fn.init = function(selector, context, root) {
var match, elem;
// 没有selector将会返回当前this,以便创建空的jQuery对象在后面会用到。
if (!selector) {
return this;
}
// 获得初始化文档的jQuery对象
root = root || rootjQuery;
// 处理参数为字符串参数
if (typeof selector === "string") {
// 处理参数为DOM节点
} else if (selector.nodeType) {
// 处理参数为function
} else if (jQuery.isFunction(selector)) {
}
// 处理参数为NodeLists
return jQuery.makeArray(selector, this);
};
// init函数继承jQuery
init.prototype = jQuery.fn;
// 初始化document为jQuery对象
rootjQuery = jQuery( document );
因为这个jQuery.fn.init函数代码很多所以单独的参数类型会把他的代码单独提出来分解,下面看提出来的参数为字符串的代码。
对于字符串参数的几种调用方法参见上面脑图
// 匹配html标签写法和id选择器
// 第一个分组是 <div> 中的div,第二个分组是#id中的id
rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
// 参数为字符串处理方式
if (typeof selector === "string") {
if (selector.charAt(0) === "<" &&
selector.charAt(selector.length - 1) === ">" &&
selector.length >= 3) {
// 字符串是单标签的DOM格式直接创建正则匹配的格式以跳过正则匹配以节约性能
match = [null, selector, null];
} else {
// 匹配到DOM字符串 或者ID选择器
match = rquickExpr.exec(selector);
}
// 如果selector是一个html字符串或者是一个ID选择器
if (match && (match[1] || !context)) {
// html字符串解析
if (match[1]) {
context = context instanceof jQuery ? context[0] : context;
// 解析html(单标签或多标签)
jQuery.merge(this, jQuery.parseHTML(
match[1],
context && context.nodeType ? context.ownerDocument || context : document,
true
));
// 构建html元素时传递了第二个参数为一个对象,那么会对对象的key和value进行解析
if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
for (match in context) {
// Properties of context are called as methods if possible
if (jQuery.isFunction(this[match])) {
this[match](context[match]);
// ...and otherwise set as attributes
} else {
this.attr(match, context[match]);
}
}
}
return this;
// 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
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;
}
// 其他选择器(class、element、attr)等
} else if (!context || context.jquery) {
return (context