提起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的继承”的更多相关文章

  1. jQuery源码二之extend的实现

    extend是jQuery中一个比较核心的代码,如果有查看jQuery的源码的话,就会发现jQuery在多处调用了extend方法. 作用 对任意对象进行扩展 扩展某个实例对象 对jquery本身的实 ...

  2. jquery源码学习之extend

    jquery的extend方法现项目中经常使用,现在了解一下它的实现. 说起extend就要先了解一个jQuery的$.extend和$.fn.extend作用及区别 jQuery为开发插件提拱了两个 ...

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

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

  4. jQuery源码笔记(一):jQuery的整体结构

    jQuery 是一个非常优秀的 JS 库,与 Prototype,YUI,Mootools 等众多的 Js 类库相比,它剑走偏锋,从 web 开发的实用角度出发,抛除了其它 Lib 中一些中看但不实用 ...

  5. jQuery 源码解析一:jQuery 类库整体架构设计解析

    如果是做 web 的话,相信都要对 Dom 进行增删查改,那大家都或多或少接触到过 jQuery 类库,其最大特色就是强大的选择器,让开发者脱离原生 JS 一大堆 getElementById.get ...

  6. jQuery源码整体结构(源码2.0.3)

    拨开jQuery的面纱,最近了解了下jQuery源码整体框架.主要包括: (1)  jQuery 核心模块 (2)  sizzle 选择器引擎 (3)  Deferred 异步队列 (4)  Supp ...

  7. js菜鸟进阶-jQuery源码分析(1)-基本架构

    导读: 本人JS菜鸟一枚,为加强代码美观和编程思想.所以来研究下jQuery,有需要进阶JS的同学很适合阅读此文!我是边看代码(jquery2.2.1),边翻“javascript高级程序设计”写的, ...

  8. jQuery源码解析资源便签

    最近开始解读jQuery源码,下面的链接都是搜过来的,当然妙味课堂 有相关的一系列视频,长达100多期,就像一只蜗牛慢慢爬, 至少品读三个框架,以后可以打打怪,自己造造轮子. 完全理解jQuery源代 ...

  9. jQuery源码逐行分析学习01(jQuery的框架结构简化)

    最近在学习jQuery源码,在此,特别做一个分享,把所涉及的内容都记录下来,其中有不妥之处还望大家指出,我会及时改正.望各位大神不吝赐教!同时,这也是我的第一篇前端技术博客,对博客编写还不是很熟悉,美 ...

随机推荐

  1. [LintCode] Permuation Index

    Given a permutation which contains no repeated number, find its index in all the permutations of the ...

  2. Codeforces Round #293 (Div. 2)

    A. Vitaly and Strings 题意:两个字符串s,t,是否存在满足:s < r < t 的r字符串 字符转处理:字典序排序 很巧妙的方法,因为s < t,只要找比t字典 ...

  3. 水题 HDOJ 4727 The Number Off of FFF

    题目传送门 /* 水题:判断前后的差值是否为1,b[i]记录差值,若没有找到,则是第一个出错 */ #include <cstdio> #include <iostream> ...

  4. DataGrid排序

    DataGrid是ASP.NET中非常重要的一个控件.它能方便的让我们实现编辑.排序功能:但是排序功能默认的是升序(ASC),能不能让DataGrid同时实现升降序排列呢?这篇文章将给你一个比较好的解 ...

  5. 分拆素数和[HDU2098]

    分拆素数和 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  6. TYVJ P1053 字符串的展开 Label:字符 水

    背景 NOIP2007年提高组第2道 描述 在初赛普及组的“阅读程序写结果”的问题中,我们曾给出一个字符串展开的例子:如果在输入的字符串中,含有类似于“d-h”或“4-8”的子串,我们就把它当作一种简 ...

  7. 【NOI2015】荷马史诗

    追逐影子的人,自己就是影子. ——荷马 Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷马史诗>.但是由<奥德赛>和& ...

  8. eclipse远程调试Tomcat方法

    1.Linux中配置tomcat在catalina.sh中添加如下CATALINA_OPTS="-Xdebug  -Xrunjdwp:transport=dt_socket,address= ...

  9. event.keycode大全(javascript)

    keycode 8 = BackSpace BackSpace keycode 9 = Tab Tab keycode 12 = Clear keycode 13 = Enter keycode 16 ...

  10. #undef

    #undef 是在后面取消以前定义的宏定义 该指令的形式为 #undef 标识符 其中,标识符是一个宏名称.如果标识符当前没有被定义成一个宏名称,那么就会忽略该指令. 一旦定义预处理器标识符,它将保持 ...