jQuery.extend方法是我们常用的方法,也是jQuery源码中的基础方法。它的主要作用是:将一个或多个“源对象”合并到一个“目标对象”中,并返回目标对象。它主要有三种表现形式:

a、jQuery.extend(destination, source1, source2, source3 ....)

b、jQuery.extend( source )

c、jQuery.extend(boolean, destination, source1, source2, source3 ....)

a方式第一个参数作为“目标对象”,其它参数作为“源对象”。

b方式只有一个参数,这里的这个参数变成了“源对象”,“目标对象”变成了jQuery。说白了就是"源对象"的属性,变成jQuery函数的静态方法或属性。

c方式的第一个参数是boolean类型的,第二个参数是"目标对象",剩下的参数是“源对象”。当第一个参数的值为true时,表示对象合并时支持“深拷贝”。

知道了函数的用法,我们肯定好奇jQuery是怎么实现的,想看看jQuery的源码。不过在看jQuery源码之前,我们不妨试着写写这个方法的功能,然后在回过头来看jQuery源码,感受可能更深,看到的东西可能越多。

我们先不要给自己压力,先从最简单的开始,要实现的方法就两个参数:第一个参数是:“目标对象”,第二个参数是:“源对象”。先实现把“源对象”合并到“目标对象”中。代码如下:

  1. var Test = function(){}
  2. Test.extend0 = function(destination, source){
  3. for(var key in source){
  4. destination[key] = source[key]
  5. }
  6. return destination
  7. }

第二步实现可以传入多个参数,第一个参数是目标对象,其他参数是源对象。代码如下:

  1. Test.extend1 = function(){
  2. var destination = arguments[0]
  3. var sourceArr = Array.prototype.slice.call(arguments,1)
  4. for(var i = 0, len = sourceArr.length; i < len; i++){
  5. var source = sourceArr[i]
  6. for(var key in source){
  7. destination[key] = source[key]
  8. }
  9. }
  10. return destination
  11. }

第三步实现只有一个参数时,将参数对象的属性附加给Test。代码如下:

  1. Test.extend2 = function(){
  2. var argumentsLen = arguments.length
  3. if( argumentsLen === 1 ){
  4. var source = arguments[0]
  5. for(var key in source){
  6. Test[key] = source[key]
  7. }
  8. }else{
  9. var destination = arguments[0]
  10. var sourceArr = Array.prototype.slice.call(arguments,1)
  11. for(var i = 0, len = sourceArr.length; i < len; i++){
  12. var source = sourceArr[i]
  13. for(var key in source){
  14. destination[key] = source[key]
  15. }
  16. }
  17. return destination
  18. }
  19. }

第四步实现“深拷贝”,第一个参数是是否进行深拷贝的布尔判断,第二个参数是目标对象,其他参数是源对象。代码如下:

  1. Test.extend3 = function(){
  2. var argumentsLen = arguments.length
  3. if( argumentsLen === 1 ){
  4. var source = arguments[0]
  5. for(var key in source){
  6. Test[key] = source[key]
  7. }
  8. }else{
  9. var firstItem = arguments[0]
  10. var isBoolean = typeof firstItem === "boolean"
  11. var destination = isBoolean ? arguments[1] : firstItem
  12. var startNum = isBoolean ? 2 : 1
  13. var sourceArr = Array.prototype.slice.call(arguments,startNum)
  14. for(var i = 0, len = sourceArr.length; i < len; i++){
  15. var source = sourceArr[i]
  16. if( isBoolean ){
  17. deepExtend( destination, source )
  18. }else{
  19. for(var key in source){
  20. destination[key] = source[key]
  21. }
  22. }
  23. }
  24. return destination
  25. }
  26. }
  27.  
  28. function deepExtend(destination, source){
  29. for(var key in source){
  30. var value = source[key]
  31. if( value instanceof Array ){
  32. destination[key] = arguments.callee.call( destination[key] || [], value )
  33. }else if( value instanceof Object ){
  34. destination[key] = arguments.callee.call( destination[key] || {}, value )
  35. }else{
  36. destination[key] = source[key]
  37. }
  38. }
  39. return destination
  40. }

好了,我们按照自己的思路,粗略的实现了自己的extend方法,现在就看下jQuery对extend的实现,对比学习一下。源码如下:

  1. jQuery.extend = jQuery.fn.extend = function() {
  2. var src, copyIsArray, copy, name, options, clone,
  3. target = arguments[0] || {},
  4. i = 1,
  5. length = arguments.length,
  6. deep = false;
  7.  
  8. // Handle a deep copy situation
  9. if ( typeof target === "boolean" ) {
  10. deep = target;
  11.  
  12. // skip the boolean and the target
  13. target = arguments[ i ] || {};
  14. i++;
  15. }
  16.  
  17. // Handle case when target is a string or something (possible in deep copy)
  18. if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
  19. target = {};
  20. }
  21.  
  22. // extend jQuery itself if only one argument is passed
  23. if ( i === length ) {
  24. target = this;
  25. i--;
  26. }
  27.  
  28. for ( ; i < length; i++ ) {
  29. // Only deal with non-null/undefined values
  30. if ( (options = arguments[ i ]) != null ) {
  31. // Extend the base object
  32. for ( name in options ) {
  33. src = target[ name ];
  34. copy = options[ name ];
  35.  
  36. // Prevent never-ending loop
  37. if ( target === copy ) {
  38. continue;
  39. }
  40.  
  41. // Recurse if we're merging plain objects or arrays
  42. if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
  43. if ( copyIsArray ) {
  44. copyIsArray = false;
  45. clone = src && jQuery.isArray(src) ? src : [];
  46.  
  47. } else {
  48. clone = src && jQuery.isPlainObject(src) ? src : {};
  49. }
  50.  
  51. // Never move original objects, clone them
  52. target[ name ] = jQuery.extend( deep, clone, copy );
  53.  
  54. // Don't bring in undefined values
  55. } else if ( copy !== undefined ) {
  56. target[ name ] = copy;
  57. }
  58. }
  59. }
  60. }
  61.  
  62. // Return the modified object
  63. return target;
  64. }

通过对比,我们发现:

a、jQuery在代码组织和实现上更加优雅。

b、jQuery考虑到了一些特殊情况。比如:

  1. if ( target === copy ) {
  2. continue;
  3. }

这是为了避免无限循环,“源对象”的属性指向的是“目标对象”,当合并对象时,也就是将“自己”复制为“自己的属性”。这是不可取的。

c、jQuery在数组(jQuery.isArray)和“纯粹对象”(jQuery.isPlainObject)的判断上,考虑的更精细。

先自己想思路去实现,再反过来对比学习,这种学习方法感觉挺好的。a、加强了独立思考能力。b、发现新的学习内容。c、暴漏自己的不足。

对jQuery.extend()方法的分析的更多相关文章

  1. jQuery extend方法使用及实现

    一.jQuery extend方法介绍 jQuery的API手册中,extend方法挂载在jQuery和jQuery.fn两个不同对象上方法,但在jQuery内部代码实现的是相同的,只是功能却不太一样 ...

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

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

  3. jquery.extend方法

    jquery.extend()用来扩展jquery中方法,实现插件. 1.jQuery.extend函数详细用法! 扩展jQuery静态方法. 1$.extend({ 2test:function() ...

  4. jQuery.extend方法和开发中变量的复用

    最近在用commonJS规范进行客户端开发,遇到如下问题: 一般一个模块内部可能会定义一系列变量或一系列相关变量,比如写了一个颜色选择弹框模块大概会有如下变量定义 var settings = { / ...

  5. jQuery extend方法介绍

    jQuery为开发插件提拱了两个方法,分别是: jQuery.fn.extend(object); jQuery.extend(object); jQuery.extend(object);为扩展jQ ...

  6. jQuery extend 方法使用 (转)

    方法介绍 jQuery 的 API 手册中,extend 方法挂载在 jQuery 和 jQuery.fn 两个不同的对象上,但在 jQuery 内部代码实现的是相同的,只是功能各不相同. 先看看官方 ...

  7. jQuery extend方法详解

    先说个概念的东西: jQuery为开发插件提拱了两个方法,分别是: $.fn.extend(item):为每一个实例添加一个实例方法item.($("#btn1") 会生成一个 j ...

  8. 对jQuery.isArray方法的分析

    jQuery.isArray方法应于判断是不是数组,是的话返回true,否则返回false.调用如:jQuery.isArray([]),返回true.其实现源码如下: isArray: Array. ...

  9. jQuery.extend()方法

    定义和用法 jQuery.extend()函数用于将一个或多个对象的内容合并到目标对象. 注意: 1. 如果只为$.extend()指定了一个参数,则意味着参数target被省略.此时,target就 ...

随机推荐

  1. markdown编辑

    有用的技巧之,如何实现首行空两格,把输入法切换成全角(shift+space),就可以实现一个两字符的空格了. 一级标题 二级标题 三级标题 四级标题 五级标题 六级标题 w s r s r s 文本 ...

  2. 安装程序无法初始化。请下载Adobe Support Advisor检测该问题

    adobe FLASH BUILDER 4.6在安装时出现各种各样的问题,虽然绿化版安装方便,但是平均5分钟一崩溃实在让人头大.安装时出现“安装程序无法初始化.请下载Adobe Support Adv ...

  3. 需要MARK一下,奇怪的ANDROID SDK自带的APK加密功能的问题

    花了两天时间,各种调试APP,发现问题不在于代码. 在于用了SDK里的加密,导致运行其中一个多线程中的ACTIVITY, 就会黑屏,返回按钮也没用. 发现这个问题的思路是因为,我发现连手机直接调试,一 ...

  4. 优化Android应用内存的若干方法

    原帖地址:http://www.open-open.com/lib/view/open1392013992317.html 在app开发的各个阶段中要考虑RAM的限制问题, 包括在设计阶段(正式开发之 ...

  5. Win8、Win10进入SQL server配置管理器

    使用 WIN8.WIN10 访问 SQL Server 配置管理器 因为 SQL Server 配置管理器是 Microsoft 管理控制台程序的一个管理单元而不是单独的程序,所以,当运行 Windo ...

  6. JAVA实现上传下载共享文件

    1.上传下载共享文件需要用到jcifs,先下载相关JAR包(开源项目的源码,demo,文挡.API应有尽有) https://jcifs.samba.org/src/

  7. iOS - 基于蓝牙数据交换的环境监测(温度、湿度、光照、粉尘、噪声)

    一.蓝牙外设的数据接收 二.App端显示获取数据            

  8. HTML+CSS学习笔记(3)- 认识标签(2)

    HTML+CSS学习笔记(3)- 认识标签(2) 1.使用ul,添加新闻信息列表 在浏览网页时,你会发现网页上有很多信息的列表,如新闻列表.图片列表, 这些列表就可以使用ul-li标签来完成.ul-l ...

  9. 移动Web单行文字垂直居中的问题

    单行文字垂直居中的方式你可能可以脱口而出,height和line-height设置为同样就行了,或者设置相同的padding-top和padding-bottom值. 上图是Chrome浏览器下的效果 ...

  10. MQ队列

    显示队列名dspmq 打开队列 runmqsc QMSAA 200-远程队列 dis qr(*) 显示所有队列 dis qr(saa_to_cips) all 显示队列参数 20-本地队列 查看队列深 ...