博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
分析JQuery中的'extend'
阅读量:6256 次
发布时间:2019-06-22

本文共 5806 字,大约阅读时间需要 19 分钟。

写在最前面


之前看了阮大佬的博客并且自己分析了一波,感觉意犹未尽,于是趁热自己抽时间又看了下Jquery中的extend方法源码,然后写写自己的理解。

预备工作


在看这个方法之前,我先看了下它的使用方法(jquery中文文档):

知道怎么用就可以开始看看源码啦!

喵一下源码


jquery.extend()

function () {    //-------------------一脸懵逼    var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {},        i = 1,        length = arguments.length,        deep = false;    //-------------------二脸懵逼    // Handle a deep copy situation    if (typeof target === "boolean") {        deep = target;        target = arguments[1] || {};        // skip the boolean and the target        i = 2;    }    //-------------------三脸懵逼    // Handle case when target is a string or something (possible in deep copy)    if (typeof target !== "object" && !jQuery.isFunction(target)) {        target = {};    }    //-------------------四脸懵逼    // extend jQuery itself if only one argument is passed    if (length === i) {        target = this;        --i;    }    //-------------------五脸懵逼    for (; i < length; i++) {        // Only deal with non-null/undefined values        if ((options = arguments[i]) != null) {            // Extend the base object            for (name in options) {                src = target[name];                copy = options[name];                // Prevent never-ending loop                if (target === copy) {                    continue;                }                // Recurse if we're merging plain objects or arrays                if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))) {                    if (copyIsArray) {                        copyIsArray = false;                        clone = src && jQuery.isArray(src) ? src : [];                    } else {                        clone = src && jQuery.isPlainObject(src) ? src : {};                    }                    // Never move original objects, clone them                    target[name] = jQuery.extend(deep, clone, copy);                    // Don't bring in undefined values                } else if (copy !== undefined) {                    target[name] = copy;                }            }        }    }        //-------------------不懵逼    // Return the modified object    return target;}复制代码

长还是挺长的,咱们已经分好段了,接下来一段段的看就好了

一脸懵逼


var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {},        i = 1,        length = arguments.length,        deep = false;复制代码

一般来说,开头都是进行初始化什么的,jq也不例外,第一句除了target = arguments[0] || {}以外,都是提前对变量进行声明,这是个好习惯!

target = arguments[0] || {}做了啥?我们知道或运算符 || 会进行判断,如果存在arguments[0]就将其值赋值给target,如果没有就将target声明成一个空对象。

二脸懵逼


// Handle a deep copy situation    if (typeof target === "boolean") {        deep = target;        target = arguments[1] || {};        // skip the boolean and the target        i = 2;    }复制代码

先看看英文注释,用于深拷贝的预处理。从前面我们知道,extend有两种使用方法,不记得在回去看看哟。。第二种就是第一个参数为boolean,标志着深拷贝。

进入这一步之前target是extend的第一个参数,对target进行简单的类型判断,如果是Boolean类型,说明是使用的第二种方法。

  • 首先我们用deep将这个boolean标志存下来
  • 那么target此时肯定不能指向第一个参数,于是将target指向第二个参数:target = arguments[1] || {}
  • 这里将i = 2,i是啥?现在还不知道它的作用,先不管。

三脸懵逼


// Handle case when target is a string or something (possible in deep copy)    if (typeof target !== "object" && !jQuery.isFunction(target)) {        target = {};    }复制代码

到了这一步,我们知道此时target指向第一个参数,也就是我们目标对象。等等...我们现在只知道指向的是arguments[1]并没有告诉我们这是对象,于是这里就是进一步对target的身份进行核实,你是对象这里就不会走,不是对象,抱歉!你需要变成一个对象。。

四脸懵逼


// extend jQuery itself if only one argument is passed    if (length === i) {        target = this;        --i;    }复制代码
  • 如果是第一种$.extend(obj1, obj2, ...)的话,length = 2... 这里i = 1
  • 如果是第二种$.extend(boolean, obj1, obj2)的话,length = 3... 这里i = 2

这样看来并不会存在length === i 的这种情况,jq写错了吗?其实并没有。。如果你仔细的浏览了下文档机会发现这样的一句话

也就是说参数个数为1的时候,这个if判断是成立的,将this传给了target,这个时候我们的目标对象就是jq本身。所以结合文档看源码还是挺有用的,不然真的会云里雾里的。

在这里--i之后,i的值变成0。(extend参数个数为1的情况下)

到这里,我们有个大胆的想法,这个i会不会就是target之后的对象的下标位置呢?

例如:

$.extend(obj1, obj2, obj3, obj4)target = arguments[0]length = 4i = 1  //obj2的下标复制代码
$.extend(true, obj1, obj2, obj3, obj4)target = arguments[1]length = 5i = 2  //obj2的下标复制代码
$extend(obj1)target = this  //jq本身length = 1i = 0  //obj1的下标复制代码

在三种情况下,我们得到不同的三个i,到这里i的意思应该很明显了。

五脸懵逼


for (; i < length; i++) {        // Only deal with non-null/undefined values        if ((options = arguments[i]) != null) {            // Extend the base object            for (name in options) {                src = target[name];                copy = options[name];                            // Prevent never-ending loop                if (target === copy) {                    continue;                }                // Recurse if we're merging plain objects or arrays                if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))) {                    if (copyIsArray) {                        copyIsArray = false;                        clone = src && jQuery.isArray(src) ? src : [];                    } else {                        clone = src && jQuery.isPlainObject(src) ? src : {};                    }                    // Never move original objects, clone them                    target[name] = jQuery.extend(deep, clone, copy);                    // Don't bring in undefined values                } else if (copy !== undefined) {                    target[name] = copy;                }            }        }    }复制代码

这一大段无非就是个拷贝嘛。。先别害怕。这么一大段for循环,就是对target后面参数对象进行遍历,分别将每个参数对象中的属性,拷贝到target对象中。知道了这个咱们接着看下去。

  • 首先进行了if判断(options = arguments[i]) != null这个参数是不是null,为null就跳过继续下一个。
  • 不为null就对该参数对象中的每个属性进行拷贝,这里有一点要提一下
// Prevent never-ending loop    if (target === copy) {         continue;    }复制代码

这里主要是担心参数对象的属性就是target,例如

obj2 = {
'obj1': obj1}$.extend(obj1, obj2) 复制代码

在这种情况下,会陷入死循环,这个地方,理解一下就懂了,操作的是同一个内存(对象)。

除了这一点,下面一大段就是进行类型判断然后进行赋值。配合我上一篇文章:中的深拷贝继承一起食用更佳。

还懵逼吗?


看了源码,最大的感受就是,这种经典的库,考虑真的很周全很仔细,尤其是那块死循环的判断,刚开始没理解,最后恍然大悟,理解完浑身畅快的感觉真的很棒。喝口水,切图去...哈哈。

转载地址:http://yvxsa.baihongyu.com/

你可能感兴趣的文章
Android -- 自定义View小Demo,绘制钟表时间(一)
查看>>
信息检索Reading List
查看>>
JavaWeb_JavaEE_命名规则
查看>>
申小雨命案审理延期至3月5日 警方将翻译嫌犯口供
查看>>
自动精简配置&重复数据删除核心技术点及其经济效应探究
查看>>
cncert网络安全周报35期 境内被植入后门的政府网站112个 环比上涨24.4%
查看>>
物联网到底是不是泡沫,且看英特尔交出的答案
查看>>
IPv6太落后了:中国加速服务器援建
查看>>
安防大数据应用国家工程实验室在乌鲁木齐成立
查看>>
物理引擎中velocity的单位是个什么鬼?
查看>>
[译] 全新 Android 注入器 : Dagger 2 (二)
查看>>
为什么要评审代码?
查看>>
小程序开发前的准备工作之【深入封装Component】
查看>>
AFN3.0源码解析
查看>>
oracle的drop命令
查看>>
设计与梳理企业二级流程的路线方法
查看>>
Python正则表达式指南
查看>>
使用css3制作渐变分割线
查看>>
垃圾回收概念与算法
查看>>
TFS实现需求工作项自动级联保存
查看>>