jQuery 源码解析代码及更多学习干货: 猛戳GitHub
建议下载源码然后据文章思路学习,最好自己边思考边多敲几遍。
一:剖析源码前准备
- 1.首先官网下载源码jQuery官网
- 2.选择jQuery版本并下载到本地,并在本地给自己新建件
myjQuery-1.0.1.js
(这个文件是用来仿写jQuery). - 3.创建入口文件并引入这官方jQuery和自己创建的
myjQuery-1.0.1.js
文件. - 4.开始剖析源码.
二.开始剖析
本次主要剖析jQuery选择器的封装,在平时使用jQuery时,非常容易的通过$()就可以查找相关的选择器,那么具体是如何实现的呢?跟随我来一探究竟...
首先先来做个例子: 我们先通过官方的jQuery框架输出以下几个实例:
// 传入字符串
console.log($("a")); //创建DOM节点包装成jQuery对象
// 传入HTML
console.log($("<div>")); // //创建DOM节点包装成jQuery对象
// 传入对象
console.log($(document));
// 传入选择器
console.log($('.box'));
// 传入对象
console.log($(this)); // 把传入的对象包装成jQuery对象
// 传入方法
$(function(){
console.log(11111); //这个是在页面加载完成后加载执行的,等效于在DOM文档加载完成后执行了$(document).read()方法
})
输出结果:

以下仅仅是核心的代码片段,详细代码在github上,自行下载查看.
剖析源码下载
init:function (selector,context) {
context = context || document;
var match,elem,index=0;
if(!selector){
return this;
}
/**
* 检测传过来的数据是否是字符串
* **/
if(typeof selector === "string"){
if (selector.charAt(0) === "<" && selector.charAt(selector.length-1)=== ">" && selector.length>=3) {
// 此时是HTML
match = [selector];
}
// match 有值的情况
if (match) {
/**
* 合并数组
* merge parseHTML是静态扩展方法
* **/
jQuery.merge(this, jQuery.parseHTML(selector,context));
// 查询DOM节点
} else {
elem = document.querySelectorAll(selector);
// 转化为真数组
var elems = Array.prototype.slice.call(elem);
this.length = elem.length;
for (;index = elem.length;index ++) {
this[index] = elems[index];
}
this.context = context;
this.selector = selector;
}
// HANDLE: $(DOMElement)
} else if (selector.nodeType){ //
this.context = this[0] = selector;
this.length = 1;
return this;
// $(function)
// 函数处理
} else if (isFunction( selector )) {
jQuery(document).ready(selector); // 实例对象的方法
}
/**
*makeArray 是jQuery扩展的方法
**/
return jQuery.makeArray( selector, this );
},
jQuery 扩展的静态方法
/**
* 合并数组
* [first] jQuery的实例对象 this
* [second] DOM 节点
*/
merge:function (first,second) {
var l = second.length, // 1
i = first.length, // 0
j = 0;
if (typeof l === "number") {
for ( ; j < l; j++){ // 遍历DOM节点
first[i++] = second[j];
}
} else {
while (second[j] !== undefined) {
first[i++] = second[j++];
}
}
first.length = i;
// 返回jQuery的实例对象
return first;
},
/**
* 解析HTML
* [data] 传入的数据
* [context] 返回的值
* **/
parseHTML:function (data,context) {
if (!data || typeof data !== "string") {
return null;
}
/**
* exec() 是正则方法 返回为数组
* [0] 为正则表达式相匹配的文本
* [1] 表达式相匹配的文本
* **/
// 过滤掉符号,只提取标签 "<a>" ==> "a"
var parse = rejectExp.exec(data);
// 返回一个创建DOM的元素
return [context.createElement(parse[1])];
},
/**
* 将一个类数组对象转换为真正的数组对象
* [arr] 传入的数组
* [result] 返回的数组
* **/
makeArray:function(arr,result){
var ret = result || [];
if ( arr != null ) {
if ( isArrayLike( Object( arr ) ) ) {
jQuery.merge( ret,
typeof arr === "string" ?
[ arr ] : arr
);
} else {
[].push.call( ret, arr );
}
}
return ret;
},
isReady:false,
readylist:[],// list
ready:function(){ // 事件函数
jQuery.isReady = true;
jQuery.readylist.forEach(function(callback){
callback.call(document);
})
// 清空
jQuery.readylist = null;
}
});
/**
* 定义全局函数
* **/
// 判断是否是方法
var isFunction = function isFunction( obj ) {
return typeof obj === "function" && typeof obj.nodeType !== "number";
};
// 判断是否是windows
var isWindow = function isWindow( obj ) {
return obj != null && obj === obj.window;
};
通过以上代码可以做以下几点分析:
1.$()传过来的selector数据是属于什么类型?不同的数据类型,分析不同数据类型的行为,有以下几种情况:
- 1.1 如果传过来的数据是字符串:那么要分析字符串是否是HTML标签,如果是HTML那么就通过正则提取关键字并创建一个HTM标签输出
- 1.2 如果传过来的数据是不是html元素,那么要通过querySelectorAll来查询过滤,如果可以查询到是DOM中的选择器,那么就遍历输出他的值.
- 1.3 如果传过来的元素是DOM节点,直接返回
- 1.4 如果传过来的数据是一个对象方法,那么要通过$(document).read()方法,监听拦截DOMContentLoaded方法,改变对象方法的指针然后依次加入到数组中,输出.
通过剖析jQuery选择器模块,进行测试:
测试代码:
// 创建DOM
// 传入字符串
console.log($("a")); //创建DOM节点包装成jQuery对象
// 传入HTML
console.log($("<div>")); // //创建DOM节点包装成jQuery对象
// 传入对象
console.log($(document));
// 传入选择器
console.log($('.box'));
// 传入对象
console.log($(this)); // 把传入的对象包装成jQuery对象
$(function(){
console.log(11111);
输出结果:

总结
通过剖析jQuery源码选择器部分,有以下几点个人收获:
- 1.jQuery 设计的静态属性扩展和jQuery的原型链属性扩展(实例扩展)的巧妙应用
- 2.巧妙应用正则来筛选数据
其他
jQuery 源码剖析 系列目录地址:猛戳GitHub
jQuery 源码剖析 系列预计写十篇左右,旨在加深对原生JavaScript 部分知识点的理解和深入,重点讲解 jQuery核心功能函数、选择器、Callback 原理、延时对象原理、事件绑定、jQuery体系结构、委托设计模式、dom操作、动画队列等。
如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎 star⭐️,对作者也是一种鼓励。
关注公众号回复:学习 领取前端最新最全学习资料,也可以进群和大佬一起学习交流
