终于动笔开始 jQuery 源码解析第二篇,写文章还真是有难度,要把自已懂的表述清楚,要让别人听懂真的不是一见易事。

在 jQuery 源码解析一:jQuery 类库整体架构设计解析 一文,大致描述了 jQuery 源码整体大致架构,主要分为以下几个点:

  A 通过自执行函数,在内部将 jQuery (jQuery 为一个函数,同时,在 JS 中,函数也为对象)以 window.jQuery=window.$ 引入,供用户直接便可使用 $、jQuery 调用。

      B 以 C#、Java 为例,可知存在静态方法、对象方法区别,该原理类比 jQuery ,jQuery.xxx 相当于给为其增加静态方法,而 jQuery.fn.xxx 则可类比于相当于给其增加对象方法。

      C 在 jQuery 源码内部,巧妙运用原型,直接上代码:

jQuery = function( selector, context ) {
// 用户调用 jQuery 方法,即是以 jQuer.fn.init 为构造函数所创建的对象
return new jQuery.fn.init( selector, context, rootjQuery );
}; // 在 JS 中,所有函数对象默认将有 prototype 属性
// 为 jQuery.prototype 另起一个简单的别名,即 jQuery.fn
// 其中 jQuery.fn 内部包含 constructor 属性(重新将该函数指向 jQuery)、init 函数
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
init: function( selector, context, rootjQuery ){
.....
},
// Start with an empty selector
selector: "", // The current version of jQuery being used
jquery: "1.8.3",
.....
}; // 关键一步,将 jQuery.fn.init 函数的 prototype属性 指向 jQuery.fn ,这一步相当重要
jQuery.fn.init.prototype = jQuery.fn; JS 中通过原型实现继承,其中使用最简单的介绍,JS 中对象的 __proto__ 属性===该对象 constructor 的 prototype 属性,
在调用方法以及获取属性,首先在自身查找,然后,即沿着 __proto__ 属性查找(而其等于 该对象 constructor 的 prototype 属性),
如果还没找到,继续沿着对象的 __proto__ 的 __proto__ 一步一步往上查找,最终查找到 Object.prototype.__proto__ 为止,没有即返回 undefined.

在 jQuery 源码中,同时,还大量包括扩展 jQuery 对象自身属性方法,以及扩展 jQuery.fn (jQuery.prototype)属性方法,而该些扩展功能,即通过 jQuery.fn.extend=jQuery.extend=function(){} 实现,

具体分析,请查看下述代码部分.

jQuery.extend = jQuery.fn.extend = function () {
// arguments 在 JS 可获取函数实际传入参数,其包含 length 属性
var src, copyIsArray, copy, name, options, clone,
// 可获取 arguments 类数组首个实参
target = arguments[] || {},
i = ,
length = arguments.length,
deep = false; // 若传入首个实参为 boolean 值,则做相关逻辑处理
if ( typeof target === "boolean" ) {
deep = target; // 将 target 重新赋值,如若首个实参为 boolean 值
target = arguments[i] || {};
// 同时,将 i 的值加 一,则为 i=2
i++;
} // Handle case when target is a string or something (possible in deep copy)
// 首个实参类型不等于 object 并且不等于 function 类型,则做相关逻辑处理
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
} // extend jQuery itself if only one argument is passed
// 如若传入实参仅为一个,则做下方逻辑处理
if (i === length) {
// 将 target 重新赋值,如若 jQuery.extend 则此时 this =jQuery,
// 如若 jQuery.fn.extend ,则此时 this =jQuery.fn=jQuery.prototype
target = this;
// 同时,将 i 的值减一,则 i=0
i--;
} // 如传入实参参数为 1 ,此时,扩展对象属性 this =jQuery,this=jQuery.fn=jQuery.prototype
// 如传入实参参数个数不为1,此时,将分为首个实参为 boolean 值,以及相关情况
for ( ; i < length; i++ ) {
// 首先,判断传入实际值是否为 undefined 、null
if ( (options = arguments[ i ]) != null ) {
// 再对传入实参值进行遍历操作,扩展对象属性
for (name in options) {
// 参考上方逻辑,如实参个数为1,则 target指向 this
// 如若实参个数不为1 ,则 target 指向 argument[0]
// 如若实参个数为 bool 值,则 target 指向 argument [1]
src = target[ name ];
copy = options[ name ]; // 判断需扩展对象与此时扩展属性进行比较,以防扩展对象与扩展属性相等,出现循环引用
if ( target === copy ) {
continue;
} // 如若首个参数值 boolean 值为 true 且扩展属性为 true 且 扩展属性为数组或者纯对象,进入深度复制逻辑处理
if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))) {
// 如若是数组
  //  jQuery.fn.extend(true,  { Name: "jack", age: 20, {Physics:30}}  ,{ Name: "jack",  {Math:40,English:100,Chinese:76}})
// jQuery.fn.extend( { Name: "jack", age: 20, {Physics:30}} ,{ Name: "jack", {Math:40,English:100,Chinese:76}})
             if (copyIsArray) {
copyIsArray = false; // 若此时需扩展对象 target[name] 属性(数组)进行扩展
clone = src && jQuery.isArray(src) ? src : [];
}
// 如若扩展属性为纯对象 else {
clone = src && jQuery.isPlainObject(src) ? src : {};
} // 进行递归调用,进行属性扩展
target[ name ] = jQuery.extend( deep, clone, copy ); // 直接扩展对象属性 ,如果扩展属性不为 undefined ,target[name]=copy,直接扩展对象属性 } else if (copy !== undefined) { // jQuery.fn.extend({ Name: "jack", age: 20, {Math:30}} ,{ Name: "jack", age: 20, {Math:40,English:100,Chinese:76}})
target[ name ] = copy;
} } } } // 最后,返回 target 对象 return target;
};

在 jQuery 源码中,可大量发现 jQuery.extend、jQuery.fn.extend 使用,而此时,为 jQuery对象、jQuery.fn ( jQuery.fn ) 进行方法属性扩展。

最后,有一个问题,在 jQuery 大量的链式调用,实现原理如何?大家可联想一下,在 java、C# 中要实现这种调用,在一个类中,如何实现该种功能?在 Java、C# 中,在一个类中,每个方法逻辑写完后,最终都返回 this,是不是就可以实现该功能。当然,在 C# 中,现在已有扩展方法可实现该功能。

参考资料:http://www.cnblogs.com/chyingp/archive/2013/06/03/3115210.html

jQuery 源码解析二:jQuery.fn.extend=jQuery.extend 方法探究的更多相关文章

  1. jQuery 源码解析(二十五) DOM操作模块 html和text方法的区别

    html和text都可以获取和修改DOM节点里的内容,方法如下: html(value)     ;获取匹配元素集合中的一个元素的innerHTML内容,或者设置每个元素的innerHTML内容,   ...

  2. jQuery 源码解析(二十七) 样式操作模块 坐标详解

    样式操作模块可用于管理DOM元素的样式.坐标和尺寸,本节讲解一下坐标这一块. 对于坐标来说,jQuery提供了一个offset方法用于获取第一个匹配元素的坐标或者设置所有匹配元素的坐标,还有offse ...

  3. jQuery 源码解析(二十六) 样式操作模块 样式详解

    样式操作模块可用于管理DOM元素的样式.坐标和尺寸,本节讲解一下样式相关,样式操作通过jQuery实例的css方法来实现,该方法有很多的执行方法,如下: css(obj)            ;参数 ...

  4. jQuery 源码解析(二十四) DOM操作模块 包裹元素 详解

    本节说一下DOM操作模块里的包裹元素子模块,该模块可将当前匹配的元素替换指定的DOM元素,有如下方法: wrap(html)               ;在每个匹配元素的外层添加一层DOM元素   ...

  5. jQuery 源码解析(二十三) DOM操作模块 替换元素 详解

    本节说一下DOM操作模块里的替换元素模块,该模块可将当前匹配的元素替换指定的DOM元素,有两个方法,如下: replaceWith(value)     ;使用提供的新内容来替换匹配元素集合中的每个元 ...

  6. jQuery 源码解析(二十二) DOM操作模块 复制元素 详解

    本节说一下DOM操作模块里的复制元素子模块,该模块可以复制一个DOM节点,并且可选择的设置是否复制其数据缓存对象(包含事件信息)和是否深度复制(子孙节点等),API如下: $.clone(elem, ...

  7. jQuery 源码解析(二十九) 样式操作模块 尺寸详解

    样式操作模块可用于管理DOM元素的样式.坐标和尺寸,本节讲解一下尺寸这一块 jQuery通过样式操作模块里的尺寸相关的API可以很方便的获取一个元素的宽度.高度,而且可以很方便的区分padding.b ...

  8. jQuery 源码解析(二十八) 样式操作模块 scrollLeft和scrollTop详解

    scrollLeft和scrollTop用于获取/设置滚动条的,如下: scrollLeft(val) ;读取或设置整个页面的水平滚动条距离 scrollTop(val) ;读取或设置整个页面的垂直滚 ...

  9. jquery源码解析:代码结构分析

    本系列是针对jquery2.0.3版本进行的讲解.此版本不支持IE8及以下版本. (function(){ (21, 94)     定义了一些变量和函数,   jQuery = function() ...

随机推荐

  1. 实现一个简单的FTP服务器(十四)

    此为一个网络编程的一个系列,后续会把内容补上...

  2. 专题:Windows编译x264、SDL、faac、ffmpeg过程

    Windows上编译ffmpeg完整过程,包括编译x264.SDL.faac.在Windows上编译ffmpeg需要用MinGW+msys,本专题用于记录编译过程中遇到的各种问题及解决方法,转载请注明 ...

  3. Oracle RAC OCR 的管理与维护

    OCR相当于Windows的注册表.对于Windows而言,所有的软件信息,用户,配置,安全等等统统都放到注册表里边.而集群呢,同样如此,所有和集群相关的资源,配置,节点,RAC数据库统统都放在这个仓 ...

  4. Oracle 课程九之绑定变量

    课程目标 完成本课程的学习后,您应该能够: •变量绑定的目的 •父子游标 •游标共享 •绑定窥探 •SQL语句处理流程 •硬解析.软解析.软软解析 •变量绑定的应用场景   1.游标 游标可以理解为S ...

  5. html input readonly 和 disable的区别

    Readonly和Disabled它们都能够做到使用户不能够更改表单域中的内容.但是它们之间有着微小的差别,总结如下: Readonly只针对input(text / password)和textar ...

  6. addView的误区

    如果在代码中动态使用addView(v),那么v里头所有在xml里设置好的layout_xxx全部失效!

  7. 【转】正确理解PHP程序编译时的错误信息

    我们编写程序时,无论怎样小心谨慎,犯错总是在所难免的.这些错误通常会迷惑PHP编译器.如果开发人员无法了解编译器报错信息的含义,那么这些错误信息不仅毫无用处,还会常常让人感到沮丧. 编译PHP脚本时, ...

  8. mysql explain中key_len的计算

    ken_len表示索引使用的字节数,根据这个值,就可以判断索引使用情况,特别是在组合索引的时候,判断是否所有的索引字段都被查询用到. key_len显示了条件检索子句需要的索引长度,但 ORDER B ...

  9. [BILL WEI] A potentially dangerous Request.Path value was detected from the client 异常处理办法

    我们在ASP.net中使用URL导向后, 我们在访问某个地址,或者打开某个系统页面的时候,就会报错误: A potentially dangerous Request.Path value was d ...

  10. JSP中字符编码转换问题

    问题描述:一个input.jsp页面中的参数,传递到另外一个save.jsp页面上,然后存入到数据库中,如果input.jsp页面输入偶数中文没有问题,输入奇数则出现?,存入数据库的也是?. 问题源码 ...