热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

深入理解jquery中extend的实现

extend()是jQuery中一个重要的函数,作用是实现对对象的扩展,它经常用于jQuery插件的开发,jQuery内部也使用它来扩展属性方法,如noConflict方法,就是用extend方法来扩展的。下面来一起深入的再学习下jquery中extend的实现吧。

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 

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

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()来实现上面的功能。

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


推荐阅读
  • Java实战之电影在线观看系统的实现
    本文介绍了Java实战之电影在线观看系统的实现过程。首先对项目进行了简述,然后展示了系统的效果图。接着介绍了系统的核心代码,包括后台用户管理控制器、电影管理控制器和前台电影控制器。最后对项目的环境配置和使用的技术进行了说明,包括JSP、Spring、SpringMVC、MyBatis、html、css、JavaScript、JQuery、Ajax、layui和maven等。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 例如控件ID为user.id使用$(#user.id)不能得到正确的结果必须使用\\转义即$(#user\\.id)转载于:https:www.cnblogs.comrch ... [详细]
  • springboot项目引入jquery浏览器报404错误的解决办法
    本文介绍了在springboot项目中引入jquery时,可能会出现浏览器报404错误的问题,并提供了解决办法。问题可能是由于将jquery.js文件复制粘贴到错误的目录导致的,解决办法是将文件复制粘贴到正确的目录下。如果问题仍然存在,可能是其他原因导致的。 ... [详细]
  • ASP.NET jQuery 实例6 - 实现CheckBoxList成员全选或全取消
    本文介绍了在ASP.NET中使用jQuery实现CheckBoxList成员的全选或全取消操作。通过提供的页面代码示例,可以轻松实现该功能。 ... [详细]
  • 解决文件名过长下载失败问题的jQuery方案
    本文介绍了使用jQuery解决文件名过长导致下载失败的问题。原方案中存在文件名部分丢失的问题,通过动态生成隐藏域表单并提交的方式来解决。详细的解决方案和代码示例在文章中给出。 ... [详细]
  • HTML5网页模板怎么加百度统计?
    本文介绍了如何在HTML5网页模板中加入百度统计,并对模板文件、css样式表、js插件库等内容进行了说明。同时还解答了关于HTML5网页模板的使用方法、表单提交、域名和空间的问题,并介绍了如何使用Visual Studio 2010创建HTML5模板。此外,还提到了使用Jquery编写美好的HTML5前端框架模板的方法,以及制作企业HTML5网站模板和支持HTML5的CMS。 ... [详细]
  • 本文介绍了如何使用jQuery和AJAX来实现动态更新两个div的方法。通过调用PHP文件并返回JSON字符串,可以将不同的文本分别插入到两个div中,从而实现页面的动态更新。 ... [详细]
  • Android实战——jsoup实现网络爬虫,糗事百科项目的起步
    本文介绍了Android实战中使用jsoup实现网络爬虫的方法,以糗事百科项目为例。对于初学者来说,数据源的缺乏是做项目的最大烦恼之一。本文讲述了如何使用网络爬虫获取数据,并以糗事百科作为练手项目。同时,提到了使用jsoup需要结合前端基础知识,以及如果学过JS的话可以更轻松地使用该框架。 ... [详细]
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • Node.js学习笔记(一)package.json及cnpm
    本文介绍了Node.js中包的概念,以及如何使用包来统一管理具有相互依赖关系的模块。同时还介绍了NPM(Node Package Manager)的基本介绍和使用方法,以及如何通过NPM下载第三方模块。 ... [详细]
  • 随着前端技术的发展,越来越多的开发者开始使用react、vue等web框架,但很少有人深入理解这些框架的源码。然而,这些框架底层都是由原生的javascript构建而成。对于初学前端的人来说,可能会认为javascript很容易上手,但实际上只是因为它被高度封装了。与能够使用封装类的人相比,能够理解框架原理的人则处于另一个层面。本文将深入剖析jquery源码,探寻框架底层的原理,帮助读者更好地理解web框架的运行机制。 ... [详细]
  • 本文讨论了如何使用jQuery的load方法来获取被load页面中所有a标签的集合,类似于$("a")的用法。 ... [详细]
  • 本文介绍了在满足特定条件时如何在输入字段中使用默认值的方法和相应的代码。当输入字段填充100或更多的金额时,使用50作为默认值;当输入字段填充有-20或更多(负数)时,使用-10作为默认值。文章还提供了相关的JavaScript和Jquery代码,用于动态地根据条件使用默认值。 ... [详细]
  • jQuery实现简单的动画效果及用法详解
    本文详细介绍了使用jQuery实现简单动画效果的方法,包括显示/隐藏、向上收缩/向下展开、淡入/淡出、自定义动画等。同时提供了具体的用法示例,并解释了参数的含义和使用技巧。通过本文的学习,读者可以掌握如何使用jQuery实现各种动画效果,为网页增添生动和互动性。 ... [详细]
author-avatar
llllllw_wlllllll
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有