jQuery源码研究的范本是3.3.1版本。
昨天看的是jQuery
源码中最顶部的模块规范判断部分,其主要作用是针对所处不同环境支持的模块规范给出兼容性操作。而jQuery
真正主体的部分是在工厂函数中的,在里面实现了所有功能,下面我将工厂函数的函数体按行标记分割成许多小的模块,分割的依据是按照功能块的不同,下面列出我分割好的jQuery简化框架:
(function(global, factory){
"use strict";
//模块规范判断
if ( typeof module === "object" && typeof module.exports === "object" ) { //CommonJS类规范判断,由于nodejs支持CommonJS规范,所以判断此条件成立时,则执行下列语句来兼容nodejs
module.exports = global.document ? //三目运算符:先判断环境是否支持window.document属性
factory( global, true ) : //如支持,module.exports = factory( global, true ),把jQ工厂函数作为模块暴露到node.js里面。
function( w ) { //如不支持,就通过本行的匿名函数抛出错误,并返回jQ的工厂函数,但功能是否都支持,就鬼知道了...
if ( !w.document ) {
throw new Error( "jQuery requires a window with a document" );
}
return factory( w );
};
} else { //如果没有使用CommonJS规范的框架,就直接引入jQ工厂函数
factory( global );
}
//匿名函数传入两个参数:typeof window !== "undefined" ? window : this 和 jQ工厂函数(jq的完成功能在此)
})(typeof window !== "undefined" ? window : this, function(window, noGlobal){
// line:(48 - 144) 定义一些变量和函数 jQuery = function(){}
// line: (146 - 225) 为jQ对象添加一些方法和属性
// line: (227 - 294) jQ的继承方法
// line: (296 - 471) jQuery.extend({}) 为jQ对象扩展一些工具方法
// line: (499 - 2752) Sizzle : 复杂选择器的实现
// line: (3225 - 3417) Callbacks : 回调对象 : 对函数的统一管理
// line: (3460 - 3806) Deferred : 延迟对象 : 对异步的统一管理
// line: (3976 - 4326) data() : 数据缓存
// line: (4329 - 4461) queue() : 队列方法 : 执行顺序的管理
// line: (4462 - 4669) show()、hide()、toggle()等方法的实现
// line: (4861 - 5588) on() 等事件相关的操作方法
// line: (5591 - 6058) DOM操作 : 添加 删除 获取 包装 DOM筛选
// line: (6062 - 6679) css() : 样式的操作
// line: (6682 - 7487) animate() : 运动的方法
// line: (6682 - 7487) animate() : 运动的方法
// line: (7490 - 7777) 表单元素的属性操作
// line: (7790 - 7962) addClass、removeClass 等样式类方法
// line: (7967 - 8143) val() 等方法
// line: (8151 - 8336) trigger() 方法
// line: (8388 - 8526) 表单转换 serialize() 方法
// line: (8529 - 9929) 提交的数据和ajax() : ajax() load() getJSON()
// line: (9943 - 10220) offset() : 位置和尺寸的方法
// line: (10225 - 10224) bind() : 绑定方法和解绑方法
// line: (10324 - 10328) AMD模块规范兼容
// line: (10333 - 10358) 返回jQuery
})
在行48-144
中,定义了一些变量和jQuery
函数。用部分变量储存了数组和对象的一些方法,便于后续调用简化易懂,如var getProto = Object.getPrototypeOf
,就是简化获取对象属性的方法,还有var push = arr.push;
等。
还定义了一些方法,isFunction()
、isWindow()
:
//返回布尔值,判断参数是否为函数
var isFunction = function isFunction( obj ) {
return typeof obj === "function" && typeof obj.nodeType !== "number";
};
解释:当参数obj
的typeof
值全等于function
且不为节点类型时,才返回true
,严谨的判断参数是否为一个函数。
应用:$.isFunction(fn)
//判断是否为window对象,返回布尔值
var isWindow = function(obj){
return obj != null && obj === obj.window;
}
解释:window
对象是浏览器的全局变量,该对象有一个属性window
,通过window === window.window
可以判断参数全等于Window
对象。
应用:
$.isWindow(window); //true
$.isWindow(this); //true
// 浏览器环境中,顶层作用域中时this指向window,在nodejs环境中顶层作用域中全局变量是global
function toType( obj ) {
if ( obj == null ) {
return obj + ""; //返回 'null' 字符串
}
return typeof obj === "object" || typeof obj === "function" ?
class2type[ toString.call( obj ) ] || "object" :
typeof obj;
}
解释:检测参数类型,如参数为null
,则返回字符串'null'
值;如参数类型为对象或函数,则统一返回object
类型;否则就返回其相应的类型,如参数为字符串就返回string
类型。
最后来看下jQuery函数
var jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context );
},
可以看到一个构造函数jQuery.fn.init
,通过new
这个构造函数可以生成jQuery实例。
打印这个构造函数的原型看看有些什么东西?
console.log(Object.keys(jQuery.fn.init.prototype));
打印结果看图:
在jQuery.fn.init
的prototype
中有着封装的方法可供实例调用。
上面返回的构造函数jQuery.fn.init
也可以看成是jQuery.fn
的init
方法。另外注意看上面打印截图,里面也有个init
方法:
console.log(jQuery.fn.init.prototype.init === jQuery.fn.init) //true
这表明jQuery.fn
可以调用jQuery.fn.init
的原型链上的方法,则
jQuery.fn.init.prototype === jQuery.fn // true
所以在jQuery
中,在原型链上绑定了很多方法,同时
jQuery.fn === jQuery.fn.init.prototype //true
jQuery.fn.init.prototype === jQuery.prototype //true
总结:
- 调用
jQuery()
可以返回一个实例 jQuery
自己也是构造函数可以被显式new
来构建实例- 实例的方法绑定在了原型链上
emmm…,最后的总结这块,是看的网上的同类教程结论,我自己还没完全理清,因为后面的源码还没读呢,这里先写在这算是给后面看的时候提个醒也是个校验,可以叫带着问题去读吧,今天就先到这。
喜欢本文请扫下方二维码,关注微信公众号: 前端小二,查看更多我写的文章哦,多谢支持。