jQuery源码研究:化繁为简之拎出框架结构

版权声明:本文为微信公众号前端小二版权所有,如需转载可私信或关注微信公众号留言。 https://blog.csdn.net/qq_34832846/article/details/86221913

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";
};

解释:当参数objtypeof值全等于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.initprototype中有着封装的方法可供实例调用。

上面返回的构造函数jQuery.fn.init也可以看成是jQuery.fninit方法。另外注意看上面打印截图,里面也有个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…,最后的总结这块,是看的网上的同类教程结论,我自己还没完全理清,因为后面的源码还没读呢,这里先写在这算是给后面看的时候提个醒也是个校验,可以叫带着问题去读吧,今天就先到这。

喜欢本文请扫下方二维码,关注微信公众号: 前端小二,查看更多我写的文章哦,多谢支持。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_34832846/article/details/86221913