Jquery的扩展方法extend是我们在写插件的过程中常用的方法,该方法有一些重载原型,下面来看看详细的介绍吧。

通常我们使用jquery的extend时,大都是为了实现默认字段的覆盖,即若传入某个字段的值,则使用传入值,否则使用默认值。

如下面的代码:

function getOpt(option){

var _default = {

name : 'wenzi',

age : '25',

sex : 'male'

}

$.extend(_default, option);

return _default;

}

getOpt(); // {name: "wenzi", age: "25", sex: "male"}

getOpt({name:'bing'}); // {name: "bing", age: "25", sex: "male"}

getOpt({name:'bing', age:36, sex:'female'}); // {name: "bing", age: 36, sex: "female"}

那现在我们就得需要知道这个extend具体是怎么实现的了,除了实现上面的功能,还有其他作用么?那肯定是有的啦,否则我也不会问那句话了((⊙﹏⊙)b)。我们先来看看extend主要有哪些功能,然后再看实现这些功能的原理。

1. extend能实现的功能

其实从extend的含义里,我们就能知道extend是做什么的了。extend翻译成汉语后就是:延伸、扩展、推广。

1.1 将两个或更多对象的内容合并到第一个对象

我们来看看$.extend()提供的参数:jQuery.extend( target [, object1 ] [, objectN ] ),extend方法需要至少传入一个参数,第一个必需,后面的都是可选参数。若传给extend是两个或两个以上的参数都是对象类型,那么就会把后面所有对象的内容合并给target(第一个对象)上。

我们再来看看上面的例子:

function getOpt(option){

var _default = {

name : 'wenzi',

age : '25',

sex : 'male'

}

`$.extend(_default, option);`

return _default;

}

$.extend()中接收了两个参数_default和option,那么extend方法执行时,就会把option对象上字段的值全给了_default。于是_default上设置的默认值就会被option上的值覆盖。当然,若option上没有这个字段,就不会覆盖_default上字段的值。

上面函数中的extend,只是传入了两个参数,那传的参数再更多一些呢:

function getOpt(target, obj1, obj2, obj3){

$.extend(target, obj1, obj2, obj3);

return target;

}

var _default = {

name : 'wenzi',

age : '25',

sex : 'male'

}

var obj1 = {

name : 'obj1'

}

var obj2 = {

name : 'obj2',

age : '36'

}

var obj3 = {

age : '67',

sex : {'error':'sorry, I dont\'t kown'}

}

getOpt(_default, obj1, obj2, obj3); // {name: "obj2", age: "67", sex: {error: "sorry, I dont't kown"}}

这里我们传入了4个参数,然后getOpt()返回第一个参数的值。从运行的得到结果我们可以看到,属性值永远是最后一个属性的值。

还有很重要的一点,$.extend()其实是有返回值的,返回的就是修改后的第一个参数的值。如我们可以把上面的函数修改成这样:

function getOpt(target, obj1, obj2, obj3){

var result = $.extend(target, obj1, obj2, obj3);

return result; // // result即修改后的target值

}

若我们传入的参数不想被修改,我们可以用一个空对象来作为第一个参数,然后获取$.extend()的返回值:

function getOpt(target, obj1, obj2, obj3){

var result = $.extend({}, target, obj1, obj2, obj3);

return result; // // result即为{}修改后的值

}

1.2 为JQUERY扩展方法或属性

刚才我们在1.1中讲的$.extend()的例子都是传了两个或两个以上的参数,但其实只有一个参数是必须的。若只传一个参数会怎样呢。

如果只有一个参数提供给$.extend(),这意味着目标参数被省略。在这种情况下,jQuery对象本身被默认为目标对象。这样,我们可以在jQuery的命名空间下添加新的功能。这对于插件开发者希望向 jQuery 中添加新函数时是很有用的。

$.extend({

_name : 'wenzi',

_getName : function(){

return this._name;

}

})

$._name; // wenzi

$._getName(); // wenzi

这样我们就为jQuery扩展了_name属性和_getName方法。

1.3 深度拷贝和浅度拷贝

针对什么是深度拷贝,什么是浅度拷贝,我们先来看一个简单的例子。

var obj = {name:'wenzi', sex:'male'};

var obj1 = obj; // 赋值

obj1.name = 'bing';

console.log(obj.name); // bing

我们修改了obj1中的name值,结果obj中的值也跟着发生了变化,这是为什么呢。其实这就是浅度拷贝:这仅仅是将obj对象的引用地址简单的复制了一份给予变量 obj1,而并不是将真正的对象克隆了一份,因此obj和obj1指向的都是同一个地址。当修改obj1的属性或给obj1添加新属性时,obj都会受到影响。

可是如果变量的值不是对象和数组,修改后面的变量是不会影响到前面的变量:

var s = 'hello';

var t = s;

t = 'world';

console.log(s); // hello

那么深度拷贝就不是拷贝引用地址,而是实实在在的复制一份新对象给新的变量。 在上面使用$.extend()中,都是使用的浅度拷贝,因此若后面的参数值是object类型或array类型,修改_default(target)的值,就会影响后面参数的值。

如我们使用getOpt(_default, obj1, obj2, obj3);得到的_default值是{name: “obj2”, age: “67”, sex: {error: “sorry, I dont't kown”}},可是若:

_default.sex.error = 'hello world';

那么obj3.sex.error也会跟着修改,因为obj3.sex是一个object类型。

不过$.extend()也提供了深度拷贝的方法:jQuery.extend( [deep ], target, object1 [, objectN ] ) 。若第一个参数是boolean类型,且值是true,那么就会把第二个参数作为目标参数进行合并。

var obj = {name:'wenzi', score:80};

var obj1 = {score:{english:80, math:90}}

$.extend(true, obj, obj1);

obj.score.english = 10;

console.log(obj.score.english); // 10

console.log(obj1.score.english); // 80

执行后我们发现,无论怎么修改obj.score里的值,都不会影响到obj1.score了。

2. jQuery中extend实现原理

其实不看源码,对extend大致的过程应该也是了解的:对后一个参数进行循环,然后把后面参数上所有的字段都给了第一个字段,若第一个参数里有相同的字段,则进行覆盖操作,否则就添加一个新的字段。

下面是jQuery中关于extend的源码,我就在源码上进行注释讲解了,随后再在后面进行总结:

// 为与源码的下标对应上,我们把第一个参数称为`第0个参数`,依次类推

jQuery.extend = jQuery.fn.extend = function() {

var options, name, src, copy, copyIsArray, clone,

target = arguments[0] || {}, // 默认第0个参数为目标参数

i = 1, // i表示从第几个参数凯斯想目标参数进行合并,默认从第1个参数开始向第0个参数进行合并

length = arguments.length,

deep = false; // 默认为浅度拷贝

// 判断第0个参数的类型,若第0个参数是boolean类型,则获取其为true还是false

// 同时将第1个参数作为目标参数,i从当前目标参数的下一个

// Handle a deep copy situation

if ( typeof target === "boolean" ) {

deep = target;

// Skip the boolean and the target

target = arguments[ i ] || {};

i++;

}

// 判断目标参数的类型,若目标参数既不是object类型,也不是function类型,则为目标参数重新赋值

// Handle case when target is a string or something (possible in deep copy)

if ( typeof target !== "object" && !jQuery.isFunction(target) ) {

target = {};

}

// 若目标参数后面没有参数了,如$.extend({_name:'wenzi'}), $.extend(true, {_name:'wenzi'})

// 则目标参数即为jQuery本身,而target表示的参数不再为目标参数

// Extend jQuery itself if only one argument is passed

if ( i === length ) {

target = this;

i--;

}

// 从第i个参数开始

for ( ; i < length; i++ ) {

// 获取第i个参数,且该参数不为null和undefind,在js中null和undefined,如果不区分类型,是相等的,null==undefined为true,

// 因此可以用null来同时过滤掉null和undefind

// 比如$.extend(target, {}, null);中的第2个参数null是不参与合并的

// Only deal with non-null/undefined values

if ( (options = arguments[ i ]) != null ) {

// 使用for~in获取该参数中所有的字段

// Extend the base object

for ( name in options ) {

src = target[ name ]; // 目标参数中name字段的值

copy = options[ name ]; // 当前参数中name字段的值

// 若参数中字段的值就是目标参数,停止赋值,进行下一个字段的赋值

// 这是为了防止无限的循环嵌套,我们把这个称为,在下面进行比较详细的讲解

// Prevent never-ending loop

if ( target === copy ) {

continue;

}

// 若deep为true,且当前参数中name字段的值存在且为object类型或Array类型,则进行深度赋值

// Recurse if we're merging plain objects or arrays

if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {

// 若当前参数中name字段的值为Array类型

// 判断目标参数中name字段的值是否存在,若存在则使用原来的,否则进行初始化

if ( copyIsArray ) {

copyIsArray = false;

clone = src && jQuery.isArray(src) ? src : [];

} else {

// 若原对象存在,则直接进行使用,而不是创建

clone = src && jQuery.isPlainObject(src) ? src : {};

}

// 递归处理,此处为2.2

// Never move original objects, clone them

target[ name ] = jQuery.extend( deep, clone, copy );

// deep为false,则表示浅度拷贝,直接进行赋值

// 若copy是简单的类型且存在值,则直接进行赋值

// Don't bring in undefined values

} else if ( copy !== undefined ) {

// 若原对象存在name属性,则直接覆盖掉;若不存在,则创建新的属性

target[ name ] = copy;

}

}

}

}

// 返回修改后的目标参数

// Return the modified object

return target;

};

源码分析完了,下面我们来讲解下源码中存在的几个难点和重点。

2.1 若参数中字段的值就是目标参数,停止赋值

在源码中进行了一下这样的判断:

// Prevent never-ending loop

if ( target === copy ) {

continue;

}

为什么要有这样的判断,我们来看一个简单的例子,如果没有这个判断会怎么样:

var _default = {name : 'wenzi'};

var obj = {name : _default}

$.extend(_default, obj);

console.log(_default);

输出的_default是什么呢:

_default = {name : _default};

_default是object类型,里面有个字段name,值是_default,而_default是object类型,里面有个字段name,值是_default……,无限的循环下去。于是jQuery中直接不进行操作,跳过这个字段,进行下一个字段的操作。

2.2 深度拷贝时进行递归处理

我们在前面稍微的讲解了一下,变量值为简单类型(如number, string, boolean)进行赋值时是不会影响上一个变量的值的,因此,如果当前字段的值为Object或Array类型,需要对其进行拆分,直到字段的值为简单类型(如number, string, boolean)时才进行赋值操作。

3. $.extend()与$.fn.extend()

上面讲解的全都是$.extend(),根本就没讲$.fn.extend() 。可是,你有没有发现一个细节,在这段代码的第一行是怎么写的:

jQuery.extend = jQuery.fn.extend = function(){}

也就是说$.extend()与$.fn.extend()共用的是同一个函数体,所有的操作都是一样的,只不过两个extend使用的对象不同罢了:$.extend()是在jQuery($)上进行操作的;而$.fn.extend()是在jQuery对象上进行操作的,如$(‘div').extend()

4. 总结

这就是jQuery中extend的实现,以后若我们需要用到上面的功能时,除了使用$.extend(),我们也可以在不引入jQuery框架的情况下,自己写一个简单的extend()来实现上面的功能。

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

c语言中extend用法,深入理解jquery中extend的实现相关推荐

  1. c语言中public 用法,深入理解C++中public、protected及private用法

    初学C++的朋友经常在类中看到public,protected,private以及它们在继承中表示的一些访问范围,很容易搞糊涂.今天本文就来十分分析一下C++中public.protected及pri ...

  2. 关于c语言中EOF用法的理解

    作者:Senlern 转载请注明,原文链接:http://blog.csdn.net/zhang429350061/article/details/8760636 首先看一下EOF的官方解释: 计算机 ...

  3. c语言中ndigit用法,求C语言中头文件及函数的含意的总分类

    ALLOC.H 说明内存管理函数(分配.释放等). ASSERT.H 定义 assert调试宏. BIOS.H 说明调用IBM-PC ROM BIOS子程序的各个函数. CONIO. H 说明调用DO ...

  4. python语言strip的作用_Python语言中的strip()的理解

    本文主要向大家介绍了Python语言中的strip()的理解,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助. 在看到Python中strip的时候产生了疑问 strip() 用于移 ...

  5. c语言中用了continue头文件,c语言中continue用法是什么?

    c语言中continue用法是什么? continue 语句的作用是跳过循环体中剩余的语句而强制进入下一次循环. continue语句只用在 while.for 循环中,常与 if 条件语句一起使用, ...

  6. java 函数fun_c语言中fun用法详解_后端开发

    Java Dao层的作用_后端开发 Dao层叫数据访问层,属于一种比较底层,比较基础的操作,可以具体到对于某个表或某个实体的增删改查,其Dao层的作用是对数据库的访问进行封装,从而不涉及业务,实现解耦 ...

  7. c语言中funx的作用,c语言中fun用法详解

    C语言中fun用法详解 fun函数是自定义的C/C++语言函数,函数功能多样.该函数名为"函数"英文function的简写,一般在示例和试题中使用,通常在主函数中被调用. C/C+ ...

  8. c语言 extend 函数,jQuery中$.extend()数组合并用法

    jQuery中$.extend()数组合并用法总结 jQuery为开发插件提拱了两个方法, 分别是: jQuery.fn.extend(object); jQuery.extend(object); ...

  9. C语言中const用法详解

    C语言中const用法详解 const修饰普通变量 const作用在于定义一个常量,比如const int a = 10,代表a的值不能被直接修改了,是一个常量,但仍可以通过指针的方式间接修改,如下图 ...

最新文章

  1. ecshop微信扫描支付开发
  2. Linux内核探讨-- 第六章
  3. 人工智能助力生命科学新发展 | 飞桨博士会第十一期
  4. 【转载】应广大群众的要求,今天开始连载《超容易的Linux系统管理入门书》一书...
  5. selenium3 + python - page_source页面源码
  6. 在 Centos7 用Jexus服务器 运行.Net Core 只需几步
  7. android 瀑布流效果 保存地址
  8. UIScrollView autolayout
  9. “不差钱”华为刷屏 拟募资60亿!
  10. Android Dialog Activity
  11. python自动化框架搭建过程_一步一步教你编写与搭建自动化测试框架——python篇...
  12. html文字居中单词,html文字居中
  13. 计算机硬件运行维护论文,计算机硬件维护毕业论文.doc
  14. 5GC基础:架构和网元
  15. 新版代挂网站PHP源码+去除授权/支持燃鹅代抽
  16. Excel如何按行间隔配置背景颜色
  17. Java中如何创建自定义的注解学习笔记(MD版)
  18. 自学方法测试【进行中】
  19. 机器学习 | 一个基于机器学习的简单小实践:波斯顿房价预测分析
  20. 投稿时Cover Letter的重要性

热门文章

  1. 小学三年计算机教案,小学信息技术教案三年级
  2. HM 中cfg配置文件
  3. [天权信安catf1ag] crypto,pwn部分
  4. 超赞,老外的一种避免递归查询所有子部门的树数据表设计与实现!
  5. 开源网安三款产品入选中国信通院首批《软件供应链厂商和产品名录》
  6. innerHTML动态拼接html,innerHTML动态添加html代码和脚本兼容多个浏览器
  7. 讯飞小车比赛语音控制(基础)
  8. Dijkstra算法求最短路
  9. ssh安装 和 scp命令 使用
  10. emoji表情显示问号?