jQuery.extend() 源码分析

Posted liuzhaoxu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jQuery.extend() 源码分析相关的知识,希望对你有一定的参考价值。

 jQuery.extend() 方法

  1. 可以合并对象
  2. 深拷贝与浅拷贝

技术分享图片

源码分析:

概述:  1. 首先定义变量

      options:保存每次循环遍历的arguments[i] ,

      name: 保存循环遍历对象的key值

      src:保存目标对象target的属性

      copy: 保存合并对象的属性

      copyIsArray: 如果copy是数组,用copyIsArray保存

      clone:如果目标对象是数组,用clone保存。

      target:目标对象

      deep: boolean值,判断是否是深拷贝

    2. 然后判断是否是深拷贝,如果是deep值变为target,i的值变为2,跳过前两个参数。

    3. 判断target是不是一个对象或者函数,如果都不是,就把target变为一个空对象

    4. 判断是否只有一个参数的情况

    5. 遍历需要被扩展target的参数,判断deep是否是true,如果是,就利用递归开始深克隆,如果不是就浅克隆

    6. 如果是浅克隆,就直接把copy的值赋给target[name]。

注意:不支持第一个参数写false,如果是浅拷贝就不要写。

 1 // extend方法为jQuery对象和init对象的prototype扩展方法
 2 // 同时具有独立的扩展普通对象的功能
 3 jQuery.extend = jQuery.fn.extend = function() {
 4   /*
 5   *target被扩展的对象
 6   *length参数的数量
 7   *deep是否深度操作
 8   */
 9   var options,
10     name,
11     src,
12     copy,
13     copyIsArray,
14     clone,
15     target = arguments[0] || {},
16     i = 1,
17     length = arguments.length,
18     deep = false;
19   // target为第一个参数,如果第一个参数是Boolean类型的值,则把target赋值给deep
20   // deep表示是否进行深层面的复制,当为true时,进行深度复制,否则只进行第一层扩展
21   // 然后把第二个参数赋值给target
22   if (typeof target === ‘boolean‘) {
23     deep = target;
24     target = arguments[1] || {};
25     // 将i赋值为2,跳过前两个参数
26     i = 2;
27   }
28   // target既不是对象也不是函数则把target设置为空对象。
29   if (typeof target !== ‘object‘ && !jQuery.isFunction(target)) {
30     target = {};
31   }
32   // 如果只有一个参数,则把jQuery对象赋值给target,即扩展到jQuery对象上
33   // extend(true, {});
34   // extend(obj);
35   if (length === i) {
36     // this ==> jQuery/jQuery.fn
37     target = this;
38     // 如果i=2, --i是为了让循环从1开始,如果i=1, --i是为了让循环从0开始
39     --i;
40   }
41   // 开始遍历需要被扩展到target上的参数
42   for (; i < length; i++) {
43     // 处理第i个被扩展的对象,即除去deep和target之外的对象
44     if ((options = arguments[i]) != null) {
45       // 遍历第i个对象的所有可遍历的属性
46       for (name in options) {
47         // 用src保存目标对象的属性
48         src = target[name];
49         // 用copy保存合并对象的属性
50         copy = options[name];
51         // 如果两个属性相等,就不用合并了
52         if (target === copy) {
53           continue;
54         }
55         // 当用户想要深度操作时,递归合并
56         // copy是纯对象或者是数组
57         if (
58           deep &&
59           copy &&
60           (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))
61         ) {
62           // 如果是数组
63           if (copyIsArray) {
64             // 将copyIsArray重新设置为false,为下次遍历做准备。
65             copyIsArray = false;
66             // 判断被扩展的对象中src是不是数组
67             clone = src && jQuery.isArray(src) ? src : [];
68           } else {
69             // 判断被扩展的对象中src是不是纯对象
70             clone = src && jQuery.isPlainObject(src) ? src : {};
71           }
72           // 递归调用extend方法,继续进行深度遍历
73           target[name] = jQuery.extend(deep, clone, copy);
74         }
75         // 如果不需要深度复制,则直接把copy(第i个被扩展对象中被遍历的那个键的值)
76         else if (copy !== undefined) {
77           target[name] = copy;
78         }
79       }
80     }
81   }
82   // 原对象被改变,因此如果不想改变原对象,target可传入{}
83   return target;
84 };

 

示例:

技术分享图片

如果要合并以上两个对象

需要一下6步

技术分享图片

 

以上是关于jQuery.extend() 源码分析的主要内容,如果未能解决你的问题,请参考以下文章

jQuery扩展与插件--附源码分析

jQuery源码分析笔记

jquery源码学习之extend

第五节:JQuery框架源码简析

第五节:JQuery框架源码简析

jquery源码之extend