提起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. Codeforces Round #294 (Div. 2)

    水 A. A and B and Chess /* 水题 */ #include <cstdio> #include <algorithm> #include <iost ...

  2. WPF 文本框添加水印效果

    有的时候我们需要为我们的WPF文本框TextBox控件添加一个显示水印的效果来增强用户体验,比如登陆的时候提示输入用户名,输入密码等情形.如下图所示: 这个时候我们除了可以修改TextBox控件的控件 ...

  3. 2015ACM/ICPC亚洲区长春站 J hdu 5536 Chip Factory

    Chip Factory Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)T ...

  4. python IDLE 改变窗口背景颜色

    初学Python,想必大家拿来练习最多的IDE就是Python自带的IDLE了,但是默认的代码配色及语法高亮主题确实很不适应. 能不能把IDLE配置成像sublime_text那样的主题呢? 答案是当 ...

  5. Eclipse开发JavaWeb程序报Server Tomcat v7.0 at localhost was unable to start

    出处:http://www.javaweb1024.com/info/582.jspx 原因重现: Eclipse开发JavaWeb程序,启动Servers的Tomcat服务器,突然跳出弹出框,内容显 ...

  6. SpringMVC_The resource identified by this request is only capable of generating responses with characteristics

    今天在调试springMVC的时候,在将一个对象返回为json串的时候,浏览器中出现异常: The resource identified by this request is only capabl ...

  7. java 枚举类型分析

    最近做android开发,需要用到枚举值,这样可以连续赋值,我按之前c++那样书写,如下所示: public enum ColorSelect { RED_BAGE = 0, GREEN_BAGE, ...

  8. JAVA发送邮件工具类

    import java.util.Date;import java.util.Properties; import javax.mail.BodyPart;import javax.mail.Mess ...

  9. Qt 程序退出时断言错误——_BLOCK_TYPE_IS_VALID(pHead->nBlockUse),由setAttribute(Qt::WA_DeleteOnClose)引起

    最近在学习QT,自己仿写了一个简单的QT绘图程序,但是在退出时总是报错,断言错误: 报错主要问题在_BLOCK_TYPE_IS_VALID(pHead->nBlockUse),是在关闭窗口时报的 ...

  10. linux 2.6.37-3.x.x x86_64

    /* * linux 2.6.37-3.x.x x86_64, ~100 LOC * gcc-4.6 -O2 semtex.c && ./a.out * 2010 sd@fuckshe ...