JQuery源码之“名叫extend的继承”
提起JS中的继承很多”大神“们都会提起call,apply,单纯的对象赋值继承,以及原型链继承等众多的方式以及它们的不足之处,而且还会不时的把一些面向对象的设计模式”团团“的带出来,可谓是厉害非常啊!而当被问道JQuery的extend却很少人真正去实际了解它的”秘密“。其实JQuery的继承方式就是一种拷贝方式的继承,但是在这里还有点小小的“猫腻”需要大家了解下。那么马上看这段代码:
var a1 = { prototype1: { i: "1" } };
var b1 = { prototype1: { j: 1 } };
jQuery.extend(a1, b1);
console.log(a1);
console.log(b1);
如图代码,控制台输出的a结果为:
而控制台输出的b结果为:
那么结果并不是我们希望看到的,但我们知道JQuery的extend是第二个参数对象合并到第一个对象中去的,如果要是能合并进去并且不会将原对象的子对象属性覆盖掉那就简直是perfect。
吼吼,答案是一定的。仅仅是因为我们上面代码$.extend(a,b);在JQuery内部走了一个错误的else分支,这个分支是这样的。JQuery2.1.4版代231行代码如下:
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
这行就是导致了a1的子对象i属性被覆盖的原因,因为这个分支并没有去判断当前对象是否仍然包含对象,这样我们就会马上有兴趣看看它的if()是咋个样纸。
在JQuery2.1.4版代177行至202行代码如下:
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
// Handle a deep copy situation
if ( typeof target === "boolean" ) {
deep = target;
// Skip the boolean and the target
target = arguments[ i ] || {};
i++;
}
if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
target = {};
}
if ( i === length ) {
target = this;
i--;
}
在这里提一嘴这个deep变量的含义就是深拷贝的意思,JQuery的注释也可以帮助你这样理解,吼吼,我幸运的看到了这个单词,要不然真不知道怎样叫它。
由上边的代码我们可以发现它还有一个参数,那就是在extend参数列表的first位置,在分支中我们可以清楚的看到deep默认值为false,当我们将例子中代码改为如下样子:
$.extend(true,a1,b1);
这样就使用到了,注释中所谓的深拷贝,运行后我发现console.log(a)结果就变成了:{ prototype1: { i: "1", j: 1 } };这就变成了我们理想中的样子,那么
target[ name ] = copy;
这句代码我们就更好理解了,就是针对简单键值对才适用的!而且在以上的几个if中,已经限定了传进去的目标(第一或第二个参数位置)一定要是对象,如果不传,那就是length长度与i相等,就会合并到$对象中去,JQuery的$成为目标对象。
但深拷贝又是怎样把每个对象都得到并合并的呢?我们继续看下边的代码:
for ( ; i < length; i++ ) {
if ( (options = arguments[ i ]) != null ) {
for ( name in options ) {
src = target[ name ];
copy = options[ name ];
if ( target === copy ) {
continue;
}
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 : {};
}
target[ name ] = jQuery.extend( deep, clone, copy );
从这句 for ( ; i < length; i++ ) 中我们马上就能够看出这个extend还是个拥有无限参数列表的家伙,可以随你的心意去合并众多对象(详情见Jquery 2.1.4版181行)。嘿嘿不用看了,你懂的。。。
让我们把目光转向option和下边较长的if中我们就能够明白了,如果目标对象要是复杂的就够就会拿src进行合并,而不会去new一个新的JS对象,这样就不会将原来有的覆盖掉。
而且会递归的遍历到最深一层,直到没有子对象,那就会继续执行如下代码
} else if ( copy !== undefined ) {
target[ name ] = copy;
}
这样递归返回就不会丢失任何的子对象了。
然而话说到这里还有一个地方没有解释,就是if ( target === copy ) 这个判断项。一旦子对象的属性名要是和父级的对象重名的话,那么马上就会跳出这个判断,以免造成“死递归”。
解释到这里JQuery实现的extend继承是不是也是不亚于那些平日里貌似很“牛逼”的各种对象继承呢?希望广大童鞋们也能够活学活用哈。
还是那句话有什么问题请指出,小弟不胜感激啊。么么哒!
JQuery源码之“名叫extend的继承”的更多相关文章
- jQuery源码二之extend的实现
extend是jQuery中一个比较核心的代码,如果有查看jQuery的源码的话,就会发现jQuery在多处调用了extend方法. 作用 对任意对象进行扩展 扩展某个实例对象 对jquery本身的实 ...
- jquery源码学习之extend
jquery的extend方法现项目中经常使用,现在了解一下它的实现. 说起extend就要先了解一个jQuery的$.extend和$.fn.extend作用及区别 jQuery为开发插件提拱了两个 ...
- jQuery 源码解析二:jQuery.fn.extend=jQuery.extend 方法探究
终于动笔开始 jQuery 源码解析第二篇,写文章还真是有难度,要把自已懂的表述清楚,要让别人听懂真的不是一见易事. 在 jQuery 源码解析一:jQuery 类库整体架构设计解析 一文,大致描述了 ...
- jQuery源码笔记(一):jQuery的整体结构
jQuery 是一个非常优秀的 JS 库,与 Prototype,YUI,Mootools 等众多的 Js 类库相比,它剑走偏锋,从 web 开发的实用角度出发,抛除了其它 Lib 中一些中看但不实用 ...
- jQuery 源码解析一:jQuery 类库整体架构设计解析
如果是做 web 的话,相信都要对 Dom 进行增删查改,那大家都或多或少接触到过 jQuery 类库,其最大特色就是强大的选择器,让开发者脱离原生 JS 一大堆 getElementById.get ...
- jQuery源码整体结构(源码2.0.3)
拨开jQuery的面纱,最近了解了下jQuery源码整体框架.主要包括: (1) jQuery 核心模块 (2) sizzle 选择器引擎 (3) Deferred 异步队列 (4) Supp ...
- js菜鸟进阶-jQuery源码分析(1)-基本架构
导读: 本人JS菜鸟一枚,为加强代码美观和编程思想.所以来研究下jQuery,有需要进阶JS的同学很适合阅读此文!我是边看代码(jquery2.2.1),边翻“javascript高级程序设计”写的, ...
- jQuery源码解析资源便签
最近开始解读jQuery源码,下面的链接都是搜过来的,当然妙味课堂 有相关的一系列视频,长达100多期,就像一只蜗牛慢慢爬, 至少品读三个框架,以后可以打打怪,自己造造轮子. 完全理解jQuery源代 ...
- jQuery源码逐行分析学习01(jQuery的框架结构简化)
最近在学习jQuery源码,在此,特别做一个分享,把所涉及的内容都记录下来,其中有不妥之处还望大家指出,我会及时改正.望各位大神不吝赐教!同时,这也是我的第一篇前端技术博客,对博客编写还不是很熟悉,美 ...
随机推荐
- http://blog.csdn.net/jiazimo/article/details/17265061
http://blog.csdn.net/jiazimo/article/details/17265061
- 简单几何(极角排序) POJ 2007 Scrambled Polygon
题目传送门 题意:裸的对原点的极角排序,凸包貌似不行. /************************************************ * Author :Running_Time ...
- POJ1947 Rebuilding Roads(树形DP)
题目大概是给一棵树,问最少删几条边可以出现一个包含点数为p的连通块. 任何一个连通块都是某棵根属于连通块的子树的上面一部分,所以容易想到用树形DP解决: dp[u][k]表示以u为根的子树中,包含根的 ...
- UVa10917 A Walk Through the Forest(SPFA+记忆化搜索)
题目给一张有向图,问从起点1到终点2沿着合法的路走有种走法,合法的路指从u到v的路,v到终点的距离严格小于u到终点的距离. 先SPFA预处理出所有合法的路,然后这些路肯定形成一个DAG,然后DP一下就 ...
- BZOJ2459 : [BeiJing2011]神秘好人
线段树每个节点维护d[4][4]表示四个顶点之间的最短路,合并时用Floyed合并,查询时分三段然后合并. #include<cstdio> #define N 100010 struct ...
- BZOJ3651 : 网络通信
同[ZJOI2012]网络,把每个点拆成C个点然后用LCT维护. #include<cstdio> #include<map> #define P make_pair #def ...
- POJ 2763 (树链剖分+边修改+边查询)
题目链接:http://poj.org/problem?id=2763 题目大意:某人初始在s点.有q次移动,每次移动沿着树上一条链,每经过一条边有一定花费,这个花费可以任意修改.问每次移动的花费. ...
- javascript中字符串常用操作总结、JS字符串操作大全
字符串的操作在js中非常频繁,也非常重要.以往看完书之后都能记得非常清楚,但稍微隔一段时间不用,便会忘得差不多,记性不好是硬伤啊...今天就对字符串的一些常用操作做个整理,一者加深印象,二者方便今后温 ...
- 【BZOJ】3781: 小B的询问(莫队算法)
http://www.lydsy.com/JudgeOnline/problem.php?id=3781 还能不能再裸点.. #include <cstdio> #include < ...
- js for循环,为什么一定要加var定义i变量
我知道,有些人(譬如之前的我)写js的for循环时,都不习惯加上var,这当然是语法允许的.譬如下面. for(i=0;i<10;i++){//就不写成: var i=0 alert(i); } ...