来源:慕课网 https://www.imooc.com/video/4392

jQuery整体架构

jQuery按我的理解分为五大块,选择器DOM操作事件AJAX动画, 那么为什么有13个模块?因为jQuery的设计中最喜欢的做的一件事,就是抽出共同的特性使之“模块化”,当然也是更贴近S.O.L.I.D五大原则的“单一职责SRP”了,遵守单一职责的好处是可以让我们很容易地来维护这个对象。


立即调用表达式

任何库与框架设计的第一个要点就是解决命名空间与变量污染的问题。jQuery就是利用了JavaScript函数作用域的特性,采用立即调用表达式包裹了自身的方法来解决这个问题。

写法一:

  1. (function(window, factory) {
  2. factory(window)
  3. }(this, function() {
  4. return function() {
  5. //jQuery的调用
  6. }
  7. }))

写法二:(由写法一简化得)

  1. var factory = function(){
  2. return function(){
  3. //执行方法
  4. }
  5. }
  6. var jQuery = factory();

上面的代码效果和方法1是等同的,但是这个factory有点变成了简单的工厂方法模式,需要自己调用,不像是一个单例的jQuery类,所以我们需要改成“自执行”,而不是另外调用。

写法三:

  1. (function(window, undefined) {
  2. var jQuery = function() {}
  3. // ...
  4. window.jQuery = window.$ = jQuery;
  5. })(window);

从上面的代码可看出,自动初始化这个函数,让其只构建一次。详细说一下这种写法的优势:

1、window和undefined都是为了减少变量查找所经过的scope作用域。当window通过传递给闭包内部之后,在闭包内部使用它的时候,可以把它当成一个局部变量,显然比原先在window scope下查找的时候要快一些。

2、undefined也是同样的道理,其实这个undefined并不是JavaScript数据类型的undefined,而是一个普普通通的变量名。只是因为没给它传递值,它的值就是undefined,undefined并不是JavaScript的保留字。


jQuery的类数组对象结构

首先我们看jQuery的入口都是统一的$, 通过传递参数的不同,实现了9种方法的重载:

  1. jQuery([selector,[context]])
  2. jQuery(element)
  3. jQuery(elementArray)
  4. jQuery(object)
  5. jQuery(jQuery object)
  6. jQuery(html,[ownerDocument])
  7. jQuery(html,[attributes])
  8. jQuery()
  9. jQuery(callback)

9种用法整体来说可以分三大块:选择器、dom的处理、dom加载。

换句话说jQuery就是为了获取DOM、操作DOM而存在的!所以为了更方便这些操作,让节点与实例对象通过一个桥梁给关联起来,jQuery内部就采用了一种叫“类数组对象”的方式作为存储结构,所以我们即可以像对象一样处理jQuery操作,也能像数组一样可以使用push、pop、shift、unshift、sort、each、map等类数组的方法操作jQuery对象了。

从上图可看出,jQuery对象通过对象键值对的关系保存着属性,原型保存着方法。我们来简单的模拟一个这样的数据结构:

  1. var aQuery = function (selector) {
  2. // 强制为对象 这里保证了必须是new操作符构建(太NB了这里)
  3. if (!(this instanceof aQuery)) {
  4. return new aQuery(selector);
  5. }
  6. // 个人对这里的正则抱有疑问,感觉 /(?<=#).*/ 比较好理解
  7. var elem = document.getElementById(/[^#].*/.exec(selector)[0]);
  8. // 把所有的属性与方法作为对象的key与value的方式给映射到this上,所以如上结构就可以模拟出jQuery的这样的操作了
  9. this.length = 1;
  10. this[0] = elem;
  11. this.context = document;
  12. this.selector = selector;
  13. this.get = function (num) {
  14. return this[num];
  15. }
  16. return this;
  17. }
  18. $("#test3").click(function () {
  19. $('#show3').append(aQuery("#book")[0])
  20. })

以上是模拟jQuery的对象结构,通过aQuery方法抽象出了对象创建的具体过程,这也是软件工程领域中的广为人知的设计模式-工厂方法。


jQuery中ready与load事件

jQuery有3种针对文档加载的方法:

  1. $(document).ready(function() {
  2. // ...代码...
  3. })
  4. // 上面方法的简写
  5. $(function() {
  6. // ...代码...
  7. })
  8. $(document).load(function() {
  9. // ...代码...
  10. })

ready和load谁先执行呢?答案是ready先执行,load后执行。原因请看下面DOM文档加载的步骤:

(1) 解析HTML结构。

(2) 加载外部脚本和样式表文件。

(3) 解析并执行脚本代码。

(4) 构造HTML DOM模型。 // ready

(5) 加载图片等外部文件。

(6) 页面加载完毕。 // load

ready意味着DOM结构的加载完成,此时为可以进行DOM操作的最早的时间点,对于代码来说应该越快加载越好,不需要等到图片资源都加载后才去处理框架的加载,图片资源过多load事件就会迟迟不会触发。

在jQuery种,针对高级的浏览器,使用DOMContentLoaded事件处理文档加载时机,省时省力。


jQuery多库共存处理

为了解决变量$与其他库框架或插件相冲突的情况,jQuery给出了noConflitct函数用于解决冲突的情况。

引入jQuery运行这个noConflict函数将变量$的控制权让给第一个实现它的那个库,确保jQuery不会与其他库的$对象发生冲突。

在运行这个函数后,就只能使用jQuery变量访问jQuery对象。例如,在要用到$("a")的地方,就必须换成jQuery("a"),因为$的控制权已经让出去了。

  1. // 让出$控制权
  2. jQuery.noConflict();
  3. // 使用 jQuery
  4. jQuery("aaron").show();
  5. // 使用其他库的 $()
  6. $("aaron").style.display = block’;

这个函数必须在你导入jQuery文件之后,并且在导入另一个导致冲突的库之前使用。当然也应当在其他冲突的库被使用之前,除非jQuery是最后一个导入的。

实现的代码:

  1. // 在暴露内部jQuery变量之前,先用私有属性将全局环境下旧的$和jQuery命名空间缓存起来
  2. var _jQuery = window.jQuery,
  3. _$ = window.$;
  4. jQuery.noConflict = function( deep ) {
  5. if ( window.$ === jQuery ) { // 判断当前$空间是否被jQuery接管,如果是则让出控制权给引用之前的环境
  6. window.$ = _$;
  7. }
  8. if ( deep && window.jQuery === jQuery ) { // 若deep为true,则把jQuery的控制权也让出去了
  9. window.jQuery = _jQuery;
  10. }
  11. return jQuery;
  12. };

jQuery源码解读----part 1的更多相关文章

  1. jquery源码解读

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐进增强)优雅的处理能 ...

  2. jQuery源码解读三选择器

    直接上jQuery源码截取代码 // Map over jQuery in case of overwrite _jQuery = window.jQuery, // Map over the $ i ...

  3. jQuery源码解读 --- 整体架构

    最近学习比较忙,感觉想要提高还是要读源码,所以准备考试这个考试结束就开始读jquery源码啦,加油~

  4. jQuery源码解读----part 2

    分离构造器 通过new操作符构建一个对象,一般经过四步: A.创建一个新对象 B.将构造函数的作用域赋给新对象(所以this就指向了这个新对象) C.执行构造函数中的代码 D.返回这个新对象 最后一点 ...

  5. jQuery源码解读-事件分析

    最原始的事件注册 addEventListener方法大家应该都很熟悉,它是Html元素注册事件最原始的方法.先看下addEventListener方法签名: element.addEventList ...

  6. jQuery源码解读 - 数据缓存系统:jQuery.data

    jQuery在1.2后引入jQuery.data(数据缓存系统),主要的作用是让一组自定义的数据可以DOM元素相关联——浅显的说:就是让一个对象和一组数据一对一的关联. 一组和Element相关的数据 ...

  7. jquery源码解读 (摘自jQuery源码分析系列图书(pdf)) 持续更新

    1.总体架构 1.1自调用匿名函数 //自调用匿名函数 (function(window,undefined){ //jquery code})(window); 1.这是一个自调用匿名函数.第一个括 ...

  8. jQuery源码解读一

    (function(window,undefined){...})(window); 这是一个典型的自执行的匿名函数. 为什么会有一个名为undefined的形参呢? undefined不是常量,可以 ...

  9. (转)jQuery源码解读 -- jQuery v1.10.2

    原文GitHub链接: https://github.com/chokcoco/jQuery-

随机推荐

  1. laravel 框架 数据库迁徙时SQLSTATE[420000]错误

    问题: SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key wa  s too long; max key le ...

  2. Vue router link

    html: <router-link to="test">Go to Foo</router-link> <router-link to=" ...

  3. linux centos Supervisor守护.netcore进程安装配置

    场景:当部署完.netcore程序后 使用dotnet xx.dll 后可以运行,但关闭shell或隔断时间会自动断开,此时部署的.netcore程序就不能访问了,此时需要用到Supervisor了 ...

  4. c#通用语言运行时CLR

  5. python爬虫伪装技术应用

    版权声明:本文为博主原创文章,转载 请注明出处: https://blog.csdn.net/sc2079/article/details/82423865 -写在前面 本篇博客主要是爬虫伪装技术的应 ...

  6. python:pycharm中使用pandas读取中文路径报错问题的解决方案

    假如你的文件路径名是这样的,例如:test.csv 只要它是小文件(大文件采用分块读取,后续会补上文件分块读取的相关博客),你的内存扛得住,那就直接 import pandas as pd test ...

  7. hive中计算某个日期是星期几的算法

    pmod(floor((unix_timestamp('2019-06-11 00:00:00')-unix_timestamp('1970-01-05 00:00:00'))/(3600*24)), ...

  8. 接口自动化平台搭建(二),搭建django项目与接口自动化平台的由来与功能特征

    1.创建django项目 a.使用命令创建,安装完django之后就有django-admin命令了,执行命令创建即可,命令如下: django-admin startproject my_djang ...

  9. springboot的简单了解与使用

    1. Spring Boot 1.1. 什么是Spring Boot 1.2. Spring Boot的优缺点 1.3. 快速入门 1.3.1. 设置spring boot的parent <pa ...

  10. gdb设置条件断点

    b +行号 if i==9:设置条件断点 finish:执行到当前函数返回处(退出函数) bt:打印栈帧关系