分析了一下JQuery中的extend方法实现原理


Posted in Javascript onFebruary 27, 2015

很久没有发表帖子了,今天突然分析了一下JQuery中的extend方法实现原理。目的为了提高自己对JQuery的认识,也想了解JavaScript高手是如何编写JS的,如有不足请指正。谢谢!

下面是JQuery.extend方法源代码:

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

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

        target = arguments[0] || {}, // 目标对象  

        i = 1,  

        length = arguments.length,  

        deep = false;  

    // 处理深度拷贝情况(第一个参数是boolean类型且为true)  

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

        deep = target;  

        target = arguments[1] || {};  

        // 跳过第一个参数(是否深度拷贝)和第二个参数(目标对象)  

        i = 2;  

    }  

    // 如果目标不是对象或函数,则初始化为空对象  

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

        target = {};  

    }  

    // 如果只指定了一个参数,则使用jQuery自身作为目标对象  

    if ( length === i ) {  

        target = this;  

        --i;  

    }  

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

        // Only deal with non-null/undefined values  

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

            // Extend the base object  

            for ( name in options ) {  

                src = target[ name ];  

                copy = options[ name ];  

                // Prevent never-ending loop  

                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 );  

                // 不拷贝undefined值  

                } else if ( copy !== undefined ) {  

                    target[ name ] = copy;  

                }  

            }  

        }  

    }  

    // 返回已经被修改的对象  

    return target;  

};

 从上面的分析可以看出extend函数支持深度拷贝,那么在JS中什么是深度拷贝呢?
 
    我的理解如下:如果一个对象中包含引用对象(如:数组或对象),那么拷贝该对象时不是简单的进行引用对象的地址拷贝,而是将引用对象的内容复制过来保存成一个单独的对象(如下图)。

分析了一下JQuery中的extend方法实现原理

 从上图可以看出两个学生对象共用好友对象,一方对好友对象的操作同时另一方也可见。如:你将好友的姓成了“zhangsan”那么另一个对象也能看见。

分析了一下JQuery中的extend方法实现原理

 从上图可以看出两个学生对象都有自己的好友对象,一方的修改对另一方完全是透明的(无任何影响)。以上就是我对深度复制的理解,有什么不对的请不要笑话,谢谢。

那么JQuery.extend方法怎样实现浅复制和深度复制呢?

JQuery.extend使用方式:

1、JQuery.extend(源对象)

      将源对象扩展到jQuery对象上,即把源对象的属性和方法复制到jQuery上。使用jQuery作为目标对象,源码如下:

// 如果只指定了一个参数,则使用jQuery自身作为目标对象  

if ( length === i ) {  

    target = this;  

    --i;  

}

【 实例1】:将person对象的方法扩展到jQuery对象上。

var person = {  

    sex      : 'male',  

    showName : function(name){  

            alert("Name: " + name);  

    }  

};  

jQuery.extend(person); // 将person对象扩展到jQuery($)对象上  

jQuery.showName("admin"); // Name: admin  

$.showName("admin"); // Name: amdin  

alert("Sex: " + $.sex); // Sex: male

【实例2】验证使用此种形式的extend方法为浅复制。

var person = {  

    language : ['java', 'c++', 'sql'],  

    showName : function(name){  

        alert("Name: " + name);  

    }  

};  

jQuery.extend(person); // 将person对象扩展到jQuery($)对象上  

alert($.language); // java, c++, sql  

$.language.push('PL/SQL'); // 修改扩展后的对象  

alert(person.language); // java, c++, sql, PL/SQL  

person.language.pop();  

alert($.language); // java, c++, sql

 从上面例子中可以发现,被扩展后的对象($)和源对象(person)任何一方对language数组的修改,都会影响到另一方。这就是浅复制

2、JQuery.extend(目标对象,源对象)

    将源对象的属性和方法复制到目标对象上,采用浅复制。
【实例】分别创建person和student对象,然后通过jQuery.extend方法将person的属性和方法扩展到student对象。

var person = {  

    language : ['java', 'c++', 'sql'],  

    showName : function(name){  

        alert("Name: " + name);  

    }  

};  

var student = {  

    showNum : function(num){  

        alert("Num: " + num);  

    }  

};  

jQuery.extend(student, person); // 将person对象扩展到指定的student对象上  

student.showName("admin");  

alert(student.language);

3、JQuery.extend(boolean,源对象)

    此种方式中的boolean参数表示是否采用深度复制,如果为true,则使用深度复制。
【实例】将person对象扩展到jQuery对象上

var person = {  

    language : ['java', 'c++', 'sql'],  

    showName : function(name){  

        alert("Name: " + name);  

    }  

};  

jQuery.extend(true, person); // 将person对象扩展jQuery对象上  

alert($.language); // java, c++, sql  

$.language.push('PL/SQL'); // 修改扩展后的对象  

alert(person.language); // java, c++, sql  

person.language.pop();

 从上面例子中可以看出对$.language的修改不会影响到person中的language属性。这就是深度复制

4、JQuery.extend(boolean,目标对象,源对象)

    决定是否采用深度复制将源对象扩展到目标对象上面。如下:
【实例】分别创建person和student对象,然后通过jQuery.extend方法将person的属性和方法扩展到student对象。

var person = {  

    showName : function(name){  

        alert("Name: " + name);  

    }  

};  

var student = {  

    language : ["java", "c++", "javascript"],  

    showNum : function(num){  

        alert("Num: " + num);  

    }  

};  

var target = jQuery.extend(person, student);  

alert(target.language);     // java, c++, javascript  

target.language.push("PL/SQL");  

alert(student.language);    // java, c++, javascript, PL/SQL  

student.language.pop();  

alert(target.language);     // java, c++, javascript  

var target2 = jQuery.extend(true, person, student);  

alert(target2.language);    // java, c++, javascript  

target2.language.push("PL/SQL");  

alert(student.language);    // java, c++, javascript  

student.language.pop();  

alert(target2.language);    // java, c++, javascript, PL/SQL

以上就是我对extend方法的理解,如有不正确的地方请指正。非常谢谢!

Javascript 相关文章推荐
查询json的数据结构的8种方式简介
Mar 10 Javascript
JavaScript调用浏览器打印功能实例分析
Jul 17 Javascript
JavaScript焦点事件、鼠标事件和滚轮事件使用详解
Jan 15 Javascript
深入理解Angular2 模板语法
Aug 07 Javascript
JS产生随机数的用法小结
Dec 10 Javascript
微信小程序 获取javascript 里的数据
Aug 17 Javascript
基于Vue 2.0 监听文本框内容变化及ref的使用说明介绍
Aug 24 Javascript
JavaScript fetch接口案例解析
Aug 30 Javascript
详解vue父子组件关于模态框状态的绑定方案
Jun 05 Javascript
JavaScript Array对象使用方法解析
Sep 24 Javascript
这样回答继承可能面试官更满意
Dec 10 Javascript
javascript-hashchange事件和历史状态管理实例分析
Apr 18 Javascript
JS实现在页面随时自定义背景颜色的方法
Feb 27 #Javascript
JQuery中绑定事件(bind())和移除事件(unbind())
Feb 27 #Javascript
Jquery中Event对象属性小结
Feb 27 #Javascript
jQuery中hover方法和toggle方法使用指南
Feb 27 #Javascript
JS实现往下不断流动网页背景的方法
Feb 27 #Javascript
jQuery+easyui中的combobox实现下拉框特效
Feb 27 #Javascript
asp.net+js实现金额格式化
Feb 27 #Javascript
You might like
PHP的历史和优缺点
2006/10/09 PHP
PHP的fsockopen、pfsockopen函数被主机商禁用的解决办法
2014/07/08 PHP
PHP启动windows应用程序、执行bat批处理、执行cmd命令的方法(exec、system函数详解)
2014/10/20 PHP
php中的抽象方法和抽象类
2017/02/14 PHP
详解Laravel服务容器的绑定与解析
2019/11/05 PHP
javascript背投广告代码的完善
2008/04/08 Javascript
jquery复选框CHECKBOX全选、反选
2008/08/30 Javascript
JS IE和FF兼容性问题汇总
2009/02/09 Javascript
监控 url fragment变化的js代码
2010/04/19 Javascript
网站页面自动跳转实现方法PHP、JSP(下)
2010/08/01 Javascript
javascript学习笔记(三)显示当时时间的代码
2011/04/08 Javascript
整理的比较全的event对像在ie与firefox浏览器中的区别
2013/11/25 Javascript
让javascript加载速度倍增的方法(解决JS加载速度慢的问题)
2014/12/12 Javascript
微信小程序 生命周期详解
2016/10/12 Javascript
javascript实现页面滚屏效果
2017/01/17 Javascript
微信小程序实现实时圆形进度条的方法示例
2017/02/24 Javascript
JavaScript实现左右下拉框动态增删示例
2017/03/09 Javascript
使用bootstrap插件实现模态框效果
2017/05/10 Javascript
jQuery扇形定时器插件pietimer使用方法详解
2017/07/18 jQuery
关闭Vue计算属性自带的缓存功能方法
2018/03/02 Javascript
在AngularJs中设置请求头信息(headers)的方法及不同方法的比较
2018/09/04 Javascript
Vue组件之高德地图地址选择功能的实例代码
2019/06/21 Javascript
基于javascript实现碰撞检测
2020/03/12 Javascript
python实现人人网登录示例分享
2014/01/19 Python
Python分布式进程中你会遇到的问题解析
2019/05/28 Python
Python图像处理库PIL的ImageFilter模块使用介绍
2020/02/26 Python
python生成word合同的实例方法
2021/01/12 Python
工程师自我评价怎么写
2013/09/19 职场文书
十八届三中全会感言
2014/03/10 职场文书
应聘编辑自荐信范文
2014/03/12 职场文书
领导接待方案
2014/03/13 职场文书
党的群众路线查摆剖析材料
2014/10/10 职场文书
安装配置mysql及Navicat prenium的详细流程
2021/06/10 MySQL
详解Java ES多节点任务的高效分发与收集实现
2021/06/30 Java/Android
WebRTC记录音视频流(web技术分享)
2022/02/24 Javascript
2021年国漫热度排行前十,完美世界上榜,第四是美国动画作品
2022/03/18 国漫