jQuery源码分析5-extend()方法

jQuery1.8.3中289行到353行代码,主要讲jQuery中的extend()方法的实现。

一、jQuery原型链

前面也讲解到了,每当我们调用$()时,我们会new一个jQuery的实例,而这个构造函数就是jQuery对象原型上的init事件。但是当我们对这个实例取jQuery原型上的方法时,却仍是可以取得到的,就像,

$('').jquery; // '1.8.3'

那jQuery是如何实现的呢?直接看189行。

jQuery.fn.init.prototype = jQuery.fn;

可以发现,此处将jQuery的原型赋值给了init的原型,因此构造出来的实例是可以直接访问jQuery原型上的属性和方法的。

二、extend()方法

1.常用方法

先了解下extend的方法,将会更容易明白extend的源码。

我们可以使用extend方法给jQuery扩展常用方法。我们也可以使用extend实现深浅拷贝,其实这儿的扩展,就是使用的拷贝的方式。

2.扩展方法流程

第一行进行了两次赋值,jQuery.extend = jQuery.fn.extend,因此jQuery的工具方法和实例方法是同时支持这个方法的,且实现方式是一样的。

当我们要扩展jQuery对象时,是这么写的,

jQuery.extend({
    // ...
});

此时是只有一个参数的。所以target就是这个扩展的对象,那么if ( typeof target === “boolean” )和if ( typeof target !== “object” && !jQuery.isFunction(target) )这两个if就不会进入。而由于只有一个参数,所以length是1,符合第三个if的条件,于是i变成了0,而target也被重新赋了值,指向了this。

紧接着是一个for循环,循环传入的arguments参数。然后内层有嵌套了一个for循环,循环该参数下的所有属性。用src表示复制到的对象(jQuery)下的对应的值,copy表示被复制的对象下的值,

 if ( target === copy ) {
     continue;
 }

该地方特地判断了target是否等于copy,是为了防止后面递归时照成的无限嵌套,这种特殊情况是:

var obj = {};
var obj1 = {
    b: obj
}
$.extend(obj,obj1); // 注释掉continue,控制台下看,是一个嵌套十分深的对象,此处添加这个条件就是防止这种问题。

由于extend默认是浅拷贝的,扩展对象时也是,所以接下来会走到else中,于是就直接给target(此时是jQuery)下增加个对应的属性,并赋上值。

3.浅拷贝

由于extend默认是浅拷贝的,所以我们常常可以想前面那样写,当然也可以$.extend(false,obj,obj1)这种写法。当然,像$.extend({},{a:1},{b:2} /*….*/),这样也是兼容的,会把后面所有的对象的值复制到第一个对象上去。$.extend(false,obj1)这种写法放到深拷贝一起讲。

由于第一个参数是被复制到的对象,所以target的值仍然是个object,所以前两个if也不走,而由于length不可能是1,所以也不会走,剩下的就是for循环的复制了,与扩展方法的流程一致。

4.深拷贝

由于第一个参数一定是个布尔值,此时deep值会被赋值,记录了此次拷贝是深还是浅。因为第一个参数仅仅是布尔值,并非我们所要的数据,因此target需要取后一个参数,该对象是被赋值到的对象,而i也被置为了2。

走到第二个if,if ( typeof target !== “object” && !jQuery.isFunction(target) ),这个if也是不会进入的,他的作用只是处理由于输入参数有问题,导致的拷贝错误,他会将target转成一个空对象,这里也特别过滤了function这种类型。

由于参数的个数都是大于等于3的,所以if ( length === i )同样不会进入。最后走到了两层嵌套的for循环,当deep时true,也就是深拷贝时,且满足被复制的值是一个对象或是数组时,会再次调用extend方法,进入递归。而在递归之前,jQuery对复制到的数据进行了一次处理。当他是数组时,就是用原先的数组,若不是,则新建个数组,而对象也是同样的处理。这里的特殊处理是为了应对一下问题的:

var obj = {
    a: {
        hello: 1
    }
};
var obj1 = {
    a: {
        world: 2
    }
}

console.log($.extend(true,obj1));

修改jQuery中的源码,

//...
clone = []; //src && jQuery.isArray(src) ? src : [];
//...
clone = {}; //src && jQuery.isPlainObject(src) ? src : {};
//...

我们发现在这种情况下,因为obj和obj1都有a这个属性,由于没有使用obj中的对象,所以hello:1这个值就会丢失。最后a属性下只有world:2这种情况。

进入递归后,如果复制的变量是数组或对象的话,继续递归,直到非对象和数组时,进行赋值。

如果deep直接被赋值了false的话,流程和默认情况下的拷贝是一样的。

这样,extend方法就实现了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


问题背景 最近小伙伴提了一个希望提高后台下拉列表可操作性的需求,原因是下拉列表选项过多,每次下拉选择比较费时费力且容易出错,硬着头皮啃了啃前端知识,网上搜寻了一些下拉列表实现的资料,这里总结一下。 P
// n位随机数生成 function randomNum(n) { let sString = ""; let strings = "abcdefghijklmnopq
HTML是HyperText Markup Language的简称,中文名称:超文本标记语言,它是一种用于创建网页的 标准标记语言
层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。
JavaScript 是脚本语言,是一种解释性脚本语言(代码不进行预编译)
本文由葡萄城技术团队原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 一名开发者或设计师通常可以在一秒内指出优秀的设计,但对于糟糕的设计只需最多半
本文由葡萄城技术团队原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 Excel是我们办公中常用的工具 ,它几乎能为我们处理大部分数据,友好的交互
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 原文出处:https://blog.bitsrc.io/8-tips-for-an-awesome-sign
本文由葡萄城技术团队于博客园翻译并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 如果我们自己编写从URL中分析和提取元素的代码,那么有可能会比较痛苦
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 原文出处:https://blog.bitsrc.io/what-is-deno-and-will-it-r
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 原文出处:https://blog.bitsrc.io/4-reasons-to-use-sass-in-y
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 原文出处:https://blog.bitsrc.io/vuejs-3-0-0-beta-features-
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 原文出处:https://blog.bitsrc.io/sessionstorage-and-localst
一直以来,JavaScript使用数组和对象来定义和存放结构化数据, 在这篇文章中,我们将一起深挖另一种对象Map的一切,我们将会去了解它是什么、如何遍历、都包括什么属性和方法以及优缺点是什么。
由于CSS的出现,现在的网站风格已经与它们很早之前的样子有了很大的不同。CSS的出现为原本平平无奇的网页注入了活力。这也是网站的用户体验得到进一步进化的原因。这可能就是当今几乎所有的网站或多或少都在使
自苹果推出了iPhone应用商店以来,App成为了我们生活中不可或缺的一部分,而对于实体业务也是如此,现在各行业都在推出自己的App,但有没有人想过这样一种场景,如果自己的潜在客户还没有安装你的App
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 原文出处:https://blog.bitsrc.io/10-top-chrome-extensions-f
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 原文出处:https://blog.bitsrc.io/do-your-buttons-lead-or-mi
本文由葡萄城技术团队原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 前段时间在开发【葡萄城社区】公众号时有一个功能是需要用网页授权认证地址生成二
本文由葡萄城技术团队原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 HTML5的发展改变了互联网技术趋势,前端热度依旧不减,所以对于应用开发人员