jquery技术内幕-总体架构

一、总体架构
  1. 各模块之间的依赖关系:
  2. 自调用匿名函数阅读:
  • 为什么使用自调用匿名函数?防止变量污染其他js文件的调用,保证jq库的内部使用不受影响。
  • 为什么传入window、undefined作为参数?一方面使其作为变量可以使jq内部访问window、undefined对象更快捷;另一方面,我不是很懂,原文“将window、undefined作为参数传入,可以在压缩代码是进行优化,在压缩文件中可以看到window和undefined分别变为了a和b”,另外,对于undefined来说,在某些浏览器中会被重写值,为了避免这一情况的发生,这里作为参数传入,可以保证undefined始终为undefined;
  • 匿名函数调用尽量不要省略括号末尾的分号;

二、构造jquery对象
     jq对象是一个“类数组”对象,含有length属性,连续整型属性和大量的jquery方法。
  1. jq构造函数的7种用法
  • jq方法创建jq对象,$是jq方法的缩写,jq方法不同的参数创建对象逻辑也会不同,共7种。
  • jQuery():length为0的对象
  • jQuery(html[,ownerDocument])、 jQuery(html,props)
  • jQuery(selector[,context])
  • jQuery(element)、 jQuery(elementArray)
  • jQuery(object)
  • jQuery(callback)
  • jQuery(jQuery object)

  1. 总体分析结构:
代码:
16(function( window, undefined ) {
     // 构造 jQuery 对象
22  var jQuery = (function() {
25  var jQuery = function( selector, context ) {
27  return new jQuery.fn.init( selector, context, rootjQuery
28  },
     // 一堆局部变量声明
97  jQuery.fn = jQuery.prototype = {
98  constructor: jQuery,
99  init: function( selector, context, rootjQuery ) { ... },
     //一堆原型属性和方法
319  };
322  jQuery.fn.init.prototype = jQuery.fn;
324  jQuery.extend = jQuery.fn.extend = function() { ... };
388  jQuery.extend({
     // 一堆静态属性和方法
892  });
955  return jQuery;
957 })();
     //省略其他模块的代码
9246  window.jQuery = window.$ = jQuery;
9266})( window );
1)为什么要在构造函数jQuery()内部用运算符new创建并返回另一个构造函数的实例? 如果构造函数有返回值,运算符new所创建的对象会被丢弃,返回值将作为new表达式的值。创建jQuery对象时,可以省略运算符new直接写jQuery()。
2)为什么在第97行执行jQuery.fn=jQuery.prototype,设置jQuery.fn指向构造函数jQuery()的原型对象jQuery.prototype?jQuery.fn是jQuery.prototype的简写。
3)既然调用构造函数jQuery()返回的jQuery对象实际上是构造函数jQuery.fn.init()的实例,为什么能在构造函数jQuery.fn.init()的实例上调用构造函数jQuery()的原型方法和属性?jQuery.fn.init.prototype=jQuery.fn时,用构造函数jQuery()的原型对象覆盖了构造函数jQuery.fn.init()的原型对象,从而使构造函数jQuery.fn.init()的实例也可以访问构造函数jQuery()的原型方法和属性。
4)为什么要把第25~955行的代码包裹在一个自调用匿名函数中,然后把第25行定义的构造函数jQuery()作为返回值赋值给第22行的jQuery变量?去掉这个自调用匿名函数,直接在第25行定义构造函数jQuery()不也可以吗?去掉了不是更容易阅读和理解吗?通过把这些局部变量包裹在一个自调。通过把这些局部变量包裹在一个自调。
5)为什么要覆盖构造函数jQuery()的原型对象jQuery.prototype?在原型对象jQuery.prototype上定义的属性和方法会被所有jQuery对象继承,可以有效减少每个jQuery对象所需的内存。事实上,jQuery对象只包含5种非继承属性,其余都继承自原型对象jQuery.prototype;在构造函数jQuery.fn.init()中设置了整型属性、length、selector、context;在原型方法.pushStack()中设置了prevObject。因此,也不必因为jQuery对象带有太多的属性和方法而担心会占用太多的内存。

  1. 构造函数jq.fn.init的12个分支:jq.buildFragment+jq.clean+jq.extend+jq.fn.extend:
          jQuery.buildFragment(args, nodes, scripts)执行的5个关键步骤如下:
     1)如果HTML代码符合缓存条件,则尝试从缓存对象jQuery.fragments中读取缓存的DOM元素。
     2)若上述执行不成功,则创建文档片段DocumentFragment。
     3)调用方法jQuery.clean(elems, context, fragment, scripts)将HTML代码转换为DOM元素,并存储在创建的文档片段中。
     4)如果HTML代码符合缓存条件,则把转换后的DOM元素放入缓存对象jQuery.fragments。
            HTML代码必须满足以下所有条件,才认为符合缓存条件:
    • 数组args的长度为1,且第一个元素是字符串,即数组args中只含有一段HTML代码。
    • HTML代码的长度小于512(1/2KB),否则可能会导致缓存占用的内存过大。
    • 文档对象doc是当前文档对象,即只缓存为当前文档创建的DOM元素,不缓存其他框架(iframe)的。 •HTML代码以左尖括号开头,即只缓存DOM元素,不缓存文本节点。
    • HTML代码中不能含有以下标签:<script>、<object>、<embed>、<option>、<style>。
    • 当前浏览器可以正确地复制单选按钮和复选框的选中状态checked,或者HTML代码中的单选按钮和复选按钮没有被选中。
    • 当前浏览器可以正确地复制HTML5元素,或者HTML代码中不含有HTML5标签。
     5)最后返回文档片段和缓存状态{fragment: fragment,cacheable: cacheable}。


  1. 其他原型属性和方法+静态属性和方法 
其中使用要注意:
  • 方法.size()在功能上等价于属性.length,但应该优先使用属性.length,因为它没有函数调用开销。
  • 执行时可通过方法call()和apply()指定方法执行的环境,即关键字this所引用的对象。
  • 静态方法jQuery.each(),对于数组和含有length属性的类数组对象(如函数参数对象arguments),该方法通过下标遍历,从0到length-1;对于其他对象则通过属性名遍历(for-in)。在遍历过程中,如果回调函数返回false,则结束遍历。




posted @ 2016-08-31 10:19  fuxiao82  阅读(211)  评论(0)    收藏  举报