前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >jQuery源码研究:化繁为简之拎出框架结构

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

作者头像
前端_AWhile
发布2019-08-29 13:14:06
6930
发布2019-08-29 13:14:06
举报
文章被收录于专栏:前端一会前端一会

jQuery源码研究的范本是3.3.1版本。

昨天看的是jQuery源码中最顶部的模块规范判断部分,其主要作用是针对所处不同环境支持的模块规范给出兼容性操作。而jQuery真正主体的部分是在工厂函数中的,在里面实现了所有功能,下面我将工厂函数的函数体按行标记分割成许多小的模块,分割的依据是按照功能块的不同,下面列出我分割好的jQuery简化框架:

代码语言:javascript
复制
 1(function(global, factory){
 2    "use strict";
 3
 4    //模块规范判断
 5    if ( typeof module === "object" && typeof module.exports === "object" ) {   //CommonJS类规范判断,由于nodejs支持CommonJS规范,所以判断此条件成立时,则执行下列语句来兼容nodejs
 6        module.exports = global.document ?      //三目运算符:先判断环境是否支持window.document属性
 7            factory( global, true ) :           //如支持,module.exports = factory( global, true ),把jQ工厂函数作为模块暴露到node.js里面。
 8        function( w ) {                         //如不支持,就通过本行的匿名函数抛出错误,并返回jQ的工厂函数,但功能是否都支持,就鬼知道了...
 9                if ( !w.document ) {
10                    throw new Error( "jQuery requires a window with a document" );
11                }
12                return factory( w );
13            };
14    } else {        //如果没有使用CommonJS规范的框架,就直接引入jQ工厂函数
15        factory( global );
16    }
17
18   //匿名函数传入两个参数:typeof window !== "undefined" ? window : this 和 jQ工厂函数(jq的完成功能在此) 
19})(typeof window !== "undefined" ? window : this, function(window, noGlobal){
20
21    // line:(48 - 144)     定义一些变量和函数  jQuery = function(){}
22
23    // line: (146 - 225)    为jQ对象添加一些方法和属性
24
25    // line: (227 - 294)    jQ的继承方法
26
27    // line: (296 - 471)    jQuery.extend({})   为jQ对象扩展一些工具方法
28
29    // line: (499 - 2752)   Sizzle : 复杂选择器的实现
30
31    // line: (3225 - 3417)  Callbacks : 回调对象 : 对函数的统一管理
32
33    // line: (3460 - 3806)  Deferred : 延迟对象 : 对异步的统一管理
34
35    // line: (3976 - 4326)  data() : 数据缓存
36
37    // line: (4329 - 4461)  queue() : 队列方法 : 执行顺序的管理 
38
39    // line: (4462 - 4669)  show()、hide()、toggle()等方法的实现
40
41    // line: (4861 - 5588)  on() 等事件相关的操作方法
42
43    // line: (5591 - 6058)  DOM操作 : 添加 删除 获取 包装 DOM筛选
44
45    // line: (6062 - 6679)  css() : 样式的操作
46
47    // line: (6682 - 7487)  animate() : 运动的方法
48
49    // line: (6682 - 7487)  animate() : 运动的方法
50
51    // line: (7490 - 7777)  表单元素的属性操作
52
53    // line: (7790 - 7962)  addClass、removeClass 等样式类方法
54
55    // line: (7967 - 8143)  val() 等方法
56
57    // line: (8151 - 8336)  trigger() 方法
58
59    // line: (8388 - 8526)  表单转换 serialize() 方法
60
61    // line: (8529 - 9929)  提交的数据和ajax() : ajax() load() getJSON()
62
63    // line: (9943 - 10220)  offset() : 位置和尺寸的方法
64
65    // line: (10225 - 10224)  bind() : 绑定方法和解绑方法
66
67    // line: (10324 - 10328)  AMD模块规范兼容
68
69    // line: (10333 - 10358)  返回jQuery
70})

行48-144中,定义了一些变量和jQuery函数。用部分变量储存了数组和对象的一些方法,便于后续调用简化易懂,如var getProto = Object.getPrototypeOf,就是简化获取对象属性的方法,还有var push = arr.push;等。

还定义了一些方法,isFunction()isWindow()

代码语言:javascript
复制
1//返回布尔值,判断参数是否为函数
2var isFunction = function isFunction( obj ) {
3    return typeof obj === "function" && typeof obj.nodeType !== "number";
4};

解释:当参数objtypeof值全等于function且不为节点类型时,才返回true,严谨的判断参数是否为一个函数。 应用:$.isFunction(fn)

代码语言:javascript
复制
1//判断是否为window对象,返回布尔值
2var isWindow = function(obj){
3    return obj != null && obj === obj.window;   
4}

解释:window对象是浏览器的全局变量,该对象有一个属性window,通过window === window.window可以判断参数全等于Window对象。 应用:

代码语言:javascript
复制
1$.isWindow(window); //true
2$.isWindow(this);   //true
3// 浏览器环境中,顶层作用域中时this指向window,在nodejs环境中顶层作用域中全局变量是global
代码语言:javascript
复制
1function toType( obj ) {
2    if ( obj == null ) {
3        return obj + "";    //返回 'null' 字符串
4    }
5
6    return typeof obj === "object" || typeof obj === "function" ?
7        class2type[ toString.call( obj ) ] || "object" :
8        typeof obj;
9}

解释:检测参数类型,如参数为null,则返回字符串'null'值;如参数类型为对象或函数,则统一返回object类型;否则就返回其相应的类型,如参数为字符串就返回string类型。

最后来看下jQuery函数

代码语言:javascript
复制
1var jQuery = function( selector, context ) {
2    return new jQuery.fn.init( selector, context );
3},

可以看到一个构造函数jQuery.fn.init,通过new这个构造函数可以生成jQuery实例。

打印这个构造函数的原型看看有些什么东西?

代码语言:javascript
复制
1console.log(Object.keys(jQuery.fn.init.prototype));

打印结果看图:

jQuery.fn.initprototype中有着封装的方法可供实例调用。

上面返回的构造函数jQuery.fn.init也可以看成是jQuery.fninit方法。另外注意看上面打印截图,里面也有个init方法:

代码语言:javascript
复制
1console.log(jQuery.fn.init.prototype.init === jQuery.fn.init) //true

这表明jQuery.fn可以调用jQuery.fn.init的原型链上的方法,则

代码语言:javascript
复制
1jQuery.fn.init.prototype === jQuery.fn // true

所以在jQuery中,在原型链上绑定了很多方法,同时

代码语言:javascript
复制
1jQuery.fn === jQuery.fn.init.prototype //true
2jQuery.fn.init.prototype === jQuery.prototype //true

总结:

  • 调用jQuery()可以返回一个实例
  • jQuery自己也是构造函数可以被显式new来构建实例
  • 实例的方法绑定在了原型链上

emmm…,最后的总结这块,是看的网上的同类教程结论,我自己还没完全理清,因为后面的源码还没读呢,这里先写在这算是给后面看的时候提个醒也是个校验,可以叫带着问题去读吧,今天就先到这。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-12-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端小二 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档