jQuery技术内幕:深入解析jQuery架构设计与实现原理.pdf

总体架构

入口模块

构造 jQuery 对象,jQuery()

底层支持模块

  • 工具方法 Utilities
  • 回调函数列表 Callbacks Object
  • 异步队列 Deferred Object
  • 浏览器功能测试 Support
  • 数据缓存 Data
  • 队列 Queue
  • 选择器 Sizzle

功能模块

  • 属性操作 Attributes
  • 事件系统 Events
  • DOM 遍历 Traversing
  • DOM 操作 Manipulation
  • 样式操作 CSS
    • 计算样式 & 内联样式
    • 坐标 Offset
    • 尺寸 Dimensions
  • 异步请求 Ajax
  • 动画 Effects

自调用匿名函数

创建了一个特殊的函数作用域,该作用域中的代码不会和已有的同名函数、方法和变量以及第三方库冲突

  1. // 写法 1
  2. (function(){})();
  3. // 写法 2
  4. (function(){}());
  5. // 写法 3
  6. !function(){}();

将 window 传入到自调用匿名函数中:

  • 使 window 变为局部变量,当在 jQuery 中访问 window 对象时,不需要将作用域链回退到顶层作用域,从而更快地访问 window 对象
  • 将 window 作为参数传入,可以在压缩代码时进行优化,参数 window 会被压缩为 a
  1. // 写法 1
  2. (function(){})(window);

将 undefined 传入到自调用匿名函数中:

  1. (function(window, undefined){})(window);
  • 变为局部变量,更快
  • 压缩代码优化
  • 确保参数 undefined 的值是 undefined,防止 undefined 被重写为新的值

构造 jQuery 对象

7种用法

jQuery(selector[,context]):接收一个CSS选择器表达式和可选的选择器上下文,返回一个包含了匹配的DOM元素的 jQuery 对象
jQuery(html[,ownerDocument]) | jQuery(html[,props]):用提供的 HTML 代码创建 DOM 元素
jQuery(element) | jQuery(elementArray):封装 DOM 元素为 jQuery 对象
jQuery(object):封装普通对象为 jQuery 对象
jQuery(callback):绑定 ready 事件监听函数,当 DOM 结构加载完成时执行
jQuery(jQuery object):接受一个 jQuery 对象,返回该 jQuery 对象的拷贝副本
jQuery():创建一个空 jQuery 对象

jQuery.fn.init(selector,context,rootjQuery) 的12分支

处理方式
!selector return this
selector.nodeType this.context = this[0] = selector;
this.length = 1;
return this;
“body” this.context = document;
this[0] = document.body;
this.selector = selector;
this.length = 1;
return this;
“string” 6个分支 单独标签:: document.createElement
复杂 HTML:jQuery.buildFragment
#id: document.getElementById
$(selector): return rootjQuery.find(selector);
$(selector, $(…)): return context.find(selector);
$(selector, context): return this.constructor(context).find(selector)
function return rootjQuery.ready(selector);
$($(…)) this.selector = selector.selector;
this.context = selector.context;
任意其他值 return jQuery.makeArray(selector, this)

选择器 Sizzle

http://api.jquery.com/category/selectors/
http://sizzlejs.com

sizzle 是一款纯 JS 实现的 CSS 选择器引擎

  • 完全独立,无库依赖
  • 相较于大多数常用选择器其性能非常有竞争力
  • 压缩和开启 gzip 后只有 4KB
  • 具有高扩展性和易于使用的 API
  • 支持多种浏览器:IE6+

如果浏览器支持 querySelectorAll() 则调用该方法查找元素,如果不支持,则模拟该方法的行为。

选择器表达式

  • 块表达式
    • 简单表达式:ID、CLASS、TAG
    • 属性表达式:ATTR
    • 伪类表达式:PSEUDO
      • 位置伪类 POS
      • 子元素伪类 CHILD
      • 内容伪类
      • 可见伪类
      • 表单伪类
  • 块间关系符:

    • 父子关系:”>”
    • 祖先后代关系: “ “
    • 紧挨着的兄弟元素: “+”
    • 之后的所有兄弟元素: “~”

      设计思路

      div.red > p 为例:
  • 从左向右:先查找 “div.red” 匹配的元素集合,然后查找匹配 “p” 的子元素集合

  • 从右往左:先查找 “p” 匹配的元素集合,然后检查其中每个元素的父元素是否匹配 “div.red“

  • 处理选择器表达式:解析选择器表达式中的块表达式和块间关系符

  • 处理块表达式:用块表达式的一部分查找,用剩余部分对查找结果进行过滤
  • 处理块间关系符:按照块间关系符查找,用块表达式对查找结果进行过滤

  • 从左往右:不断缩小上下文,即不断缩小查找范围

  • 从右往左:先查找后过滤

  • 从左往右:每次处理块间关系符时都需要处理未知数量的子元素或后代元素

  • 从右往左:处理块间关系符时只需要处理单个父元素或有限数量的祖先元素
  • 因此,多数情况,从右往左的查找方式其效果要高于从左往右

Sizzle 从右往左

  • 正则 chunker 负责从选择器表达式中提取块表达式和块间关系符
  • Sizzle.find(expr, context, isXML)负责查找块表达式匹配的元素集合
  • Sizzle.filter(expr, set, inplace, not)负责用块表达式过滤元素集合
  • Sizzle.selector.relative 中的块间关系过滤函数根据块间关系符过滤元素集合

样式操作 CSS

分类 方法 说明
内联样式
计算样式
.css(name, value) 获取第一个匹配元素的计算样式,或者在每个匹配元素上设置一个或多个内联样式
类样式 .addClass(value) 为每个匹配元素添加一个或多个类样式
.removeClass(value) 从每个匹配元素上移除一个或多个或全部类样式
.toggleClass(value, stateVal) 为每个匹配元素切换一个或多个或全部类样式
.hasClass(selector) 检测匹配元素是否含有指定的类样式,只要其中任意一个元素含有就返回true
坐标 .offset(options) 返回第一个匹配元素的文档坐标,或设置每个匹配元素的文档坐标
.position() 返回第一个匹配元素相对于其最近定位祖先元素的坐标
.scrollLeft() 读取第一个匹配元素的滚动条的水平偏移,或设置每个匹配元素的滚动条的水平偏移
.scrollTop() 读取第一个匹配元素的滚动条的垂直偏移,或设置每个匹配元素的滚动条的垂直偏移
尺寸 .width(size)
.height(size)
返回第一个匹配元素计算后的高度、宽度,或设置每个匹配元素的高度、宽度,包括内容 content
.innerWidth()
.innerHeight()
返回第一个匹配元素的高度、宽度,包括内容 content、内边距padding
.outerWidth(margin)
.outerHeight(margin)
返回第一个匹配元素的高度、宽度,包括内容content、内边距padding、边框border 和可选的外边框 margin