jQuery中要扩展方法或者属性都是通过extend方法实现的。所谓的jQuery插件也是通过extend方法实现的。

jQuery.extend扩展的是工具方法,也就是静态方法。jQuery.fn.extend扩展的是实例方法。

当只传入一个对象的时候,里面的方法和属性是扩展到this上的。比如:

$.extend(  {  aaa:function(){}, bbb:function(){}  }  ) ,这里的this是$,所以用这种形式$.aaa()调用。

$.fn.extend(  {  aaa:function(){}, bbb:function(){}  }  ) ,这里的this是$.fn(原型),所以用这种形式$("").aaa()调用。

当传入多个对象的时候,后面的对象都是扩展到第一个对象身上。比如:

var a ={};

$.extend(  a, {name:"hello"}, {age:30}  ),这时a = {name:"hello",age:30}

还可以做深拷贝和浅拷贝(拷贝继承)。比如:

var a = {};var b = {  name:{age:30}  };

$.extend( a , b );   a.name.age = 20,这时你打印b.name.age,你会发现也是20.这就是浅拷贝。没有对对象进行复制,只对简单字符做了复制(如果name是字符串,那么改变a.name的值,即便是浅拷贝也不会影响b.name的值)。但是你可以使用深拷贝:

$.extend( true , a , b );     a.name.age = 20,这时你打印b.name.age,你会发现是30,没有改变。因为深拷贝,无论b的属性是什么,都会重新复制一份。

jQuery.extend = jQuery.fn.extend = function() {  

  var options, name, src, copy, copyIsArray, clone,
    target = arguments[0] || {},
    i = 1,
    length = arguments.length,
    deep = false;     //默认为浅拷贝

    if ( typeof target === "boolean" ) {     //看第一个参数是否是boolean
      deep = target;     //如果是,就证明目标对象是第二个参数,第一个参数是来判断是不是深拷贝的
      target = arguments[1] || {};
      i = 2;
    }

    if ( typeof target !== "object" && !jQuery.isFunction(target) ) { //必须 为对象或者函数
      target = {};
    }

    if ( length === i ) {   //如果只有一个对象的时候,目标对象指向this,往this上扩展方法和属性
      target = this;
      --i;
    }

    for ( ; i < length; i++ ) {
      if ( (options = arguments[ i ]) != null ) {    //判断扩展的对象不是null
        for ( name in options ) {     //取对象中的属性名
          src = target[ name ];     //取目标对象的name属性值
          copy = options[ name ];   //取扩展对象的name属性值

          if ( target === copy ) {

             //解决循环引用的问题,比如:var a ={};$.extend( a , { name:a } ),如果不做这个处理,将会得到一个死循环的对象(a{name:{name:{name:{...}}}}),加了这个,就扩展不上,a还是{}
            continue;
          }

          if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {

          //如果是深拷贝,并且扩展对象的name属性值存在,并且扩展对象是一个对象自变量(或者是一个数组),就进入if语句

          
            if ( copyIsArray ) {    //如果扩展对象的name属性值是数组,进入if语句
              copyIsArray = false;
              clone = src && jQuery.isArray(src) ? src : [];

              //如果目标对象的name属性值是一个数组,就取这个数组,如果不是,就取[]

            } else {   //如果扩展对象的name属性值是对象自变量
              clone = src && jQuery.isPlainObject(src) ? src : {};

              //如果目标对象的name属性值是一个对象自变量,就取这个对象自变量,如果不是,就取{}
            }

            target[ name ] = jQuery.extend( deep, clone, copy );

            //递归调用extend,深拷贝扩展对象的name属性值(对象或者数组)到clone。

            //递归结束后,返回clone,赋值给目标元素的name属性

            //这就把扩展对象的所有属性都扩展到目标对象中了。

          } else if ( copy !== undefined ) {   
            target[ name ] = copy;
          }
        }
      }
    }

    return target;

}

jQuery中使用的是拷贝继承。

加油!

jquery源码解析:jQuery扩展方法extend的详解的更多相关文章

  1. jQuery 源码解析(三十) 动画模块 $.animate()详解

    jQuery的动画模块提供了包括隐藏显示动画.渐显渐隐动画.滑入划出动画,同时还支持构造复杂自定义动画,动画模块用到了之前讲解过的很多其它很多模块,例如队列.事件等等, $.animate()的用法如 ...

  2. jQuery 源码分析(十九) DOM遍历模块详解

    jQuery的DOM遍历模块对DOM模型的原生属性parentNode.childNodes.firstChild.lastChild.previousSibling.nextSibling进行了封装 ...

  3. jQuery 源码解析(三) pushStack方法 详解

    该函数用于创建一个新的jQuery对象,然后将一个DOM元素集合加入到jQuery栈中,最后返回该jQuery对象,有三个参数,如下: elems Array类型 将要压入 jQuery 栈的数组元素 ...

  4. jQuery 源码分析(十) 数据缓存模块 data详解

    jQuery的数据缓存模块以一种安全的方式为DOM元素附加任意类型的数据,避免了在JavaScript对象和DOM元素之间出现循环引用,以及由此而导致的内存泄漏. 数据缓存模块为DOM元素和JavaS ...

  5. jQuery源码分析(九) 异步队列模块 Deferred 详解

    deferred对象就是jQuery的回调函数解决方案,它解决了如何处理耗时操作的问题,比如一些Ajax操作,动画操作等.(P.s:紧跟上一节:https://www.cnblogs.com/grea ...

  6. 十七.jQuery源码解析之入口方法Sizzle(1)

    函数Sizzle(selector,context,results,seed)用于查找与选择器表达式selector匹配的元素集合.该函数是选择器引擎的入口. 函数Sizzle执行的6个关键步骤如下: ...

  7. jQuery 源码解析二:jQuery.fn.extend=jQuery.extend 方法探究

    终于动笔开始 jQuery 源码解析第二篇,写文章还真是有难度,要把自已懂的表述清楚,要让别人听懂真的不是一见易事. 在 jQuery 源码解析一:jQuery 类库整体架构设计解析 一文,大致描述了 ...

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

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

  9. JQuery源码解析(一)

    写在前面:本<JQuery源码解析>系列是基于一些前辈们的文章进行进一步的分析.细化.修改而写出来的,在这边感谢那些慷慨提供科普文档的技术大拿们. 要查阅JQ的源文件请下载开发版的JQ.j ...

随机推荐

  1. Fresnel Reflection Shader

    [Fresnel Reflection] One of the most used types of reflections is the Fresnel reflection. One of the ...

  2. 必看的 jQuery性能优化的38个建议

    一.注意定义jQuery变量的时候添加var关键字 这个不仅仅是jQuery,所有javascript开发过程中,都需要注意,请一定不要定义成如下: $loading = $('#loading'); ...

  3. Android中Activity的四种启动方式

    谈到Activity的启动方式必须要说的是数据结构中的栈.栈是一种只能从一端进入存储数据的线性表,它以先进后出的原则存储数据,先进入的数据压入栈底,后进入的数据在栈顶.需要读取数据的时候就需要从顶部开 ...

  4. Linux安装MySQL全过程

    操作系统:CentOS 7.2  64位 mySQL版本:mysql-5.6.35 安装过程: (1)首先从mysql官网下载 MySQL Community Server 安装包. 选择对应的版本( ...

  5. jQuery开发者眼中的AngularJS

    文章来源:http://blog.jobbole.com/76265/ AngualrJS是一个很贴心的web应用框架.它有很不错的官方文档和示例:经过在现实环境中的测试著名的TodoMVC proj ...

  6. windows命令行下批量拷贝同一后缀的文件到另外一个目录

    一个目录下有很多文件夹,想拷贝每个文件夹下面的wmv文件到另外一个目录,如果鼠标打开一个文件,拷贝一个,再打开其他的,逐一操作,很麻烦的,百度了一下,xcopy命令就可以实现:例如将C盘x1目录下所有 ...

  7. Django调试工具django-debug-toolbar安装使用教程

    在网站开发中难免要调试页面,而使用django开发站点时,可以使用django-debug-toolbar来进行调试,安装这个插件很有用,我一开始是为了查看某个页面中所有的context变量值,当然你 ...

  8. 编写高质量代码改善C#程序的157个建议——建议144:一个方法只做一件事

    建议144:一个方法只做一件事 “单一职责原则”(SRP)要求每一个类型只负责一件事情.我们将此概念扩展到方法上,就变成了:一个方法只做一件事. 回顾上一建议的代码,LocalInit和RemoteI ...

  9. 洛谷 P2596 [ZJOI2006]书架 (splay)

    题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些 ...

  10. .net 可选参数和命名参数

    可选参数,可以为方法的参数设置默认值,在调用方法的时候,如果不传递参数,就是执行默认参数. class Program { , string s = "A", DateTime d ...