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源码,在此,特别做一个分享,把所涉及的内容都记录下来,其中有不妥之处还望大家指出,我会及时改正.望各位大神不吝赐教!同时,这也是我的第一篇前端技术博客,对博客编写还不是很熟悉,美 ...
随机推荐
- Windows内核下操作字符串!
* Windows内核下操作字符串! */ #include <ntddk.h> #include <ntstrsafe.h> #define BUFFER_SIZE 1024 ...
- BZOJ3829 : [Poi2014]FarmCraft
d[x]表示走完x的子树并回到x所需的时间 f[x]表示从走到x开始计时,x子树中最晚的点安装完的最早时间 d[x]=sum(d[i]+2),i是x的孩子 f[x]的计算比较复杂: 考虑将x的各棵子树 ...
- Codeforces Round #213 (Div. 2) B. The Fibonacci Segment
#include <iostream> #include <algorithm> #include <vector> using namespace std; in ...
- More about Tair (NoSql)
一.前言 关于Tair的相关介绍请参照wiki(http://code.taobao.org/p/tair/wiki/index/)或者之前的博文,不再重复描述.区别于其它主流NoSql数据库,Tai ...
- 提升 web 应用程序的性能(一)
提升 web 应用程序的性能,找出瓶颈,加快客户端内容的速度. 作为 web 用户,我们知道页面加载或刷新的速度对其成功至关重要.本文将帮助您更好地理解影响 web 应用程序性能的因素.学 ...
- highcharts报表插件之expoting参数的使用
exporting 参数配置 本文转载自:http://blog.csdn.net/myjlvzlp/article/details/8531275 说明:导出及打印选项 打印导出功能的配置项. 1. ...
- nodejs 更新最新版本
sudo npm cache clean -f sudo npm install -g n sudo n stable
- Java泛型总结
1. 什么是泛型?泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类.可以把类型参数看作是使用参数化类型时指定的类型的 ...
- 【转】TCP协议中的三次握手和四次挥手(图解)
http://blog.csdn.net/whuslei/article/details/6667471
- Apache Storm技术实战之3 -- TridentWordCount
欢迎转载,转载请注明出处. 介绍TridentTopology的使用,重点分析newDRPCStream和stateQuery的实现机理. 使用TridentTopology进行数据处理的时候,经常会 ...