分析了一下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 相关文章推荐
js继承 Base类的源码解析
Dec 30 Javascript
JavaScript高级程序设计 阅读笔记(十四) js继承机制的实现
Aug 14 Javascript
jquery聚焦文本框与扩展文本框聚焦方法
Oct 12 Javascript
jquery ajax属性async(同步异步)示例
Nov 05 Javascript
jQuery实现列表自动滚动循环滚动展示新闻
Aug 22 Javascript
Javascript基础教程之变量
Jan 18 Javascript
BOM系列第三篇之定时器应用(时钟、倒计时、秒表和闹钟)
Aug 17 Javascript
详解vue-cli本地环境API代理设置和解决跨域
Sep 05 Javascript
LayUI表格批量删除方法
Aug 15 Javascript
详解vue+axios给开发环境和生产环境配置不同的接口地址
Aug 16 Javascript
ES6学习教程之Promise用法详解
Nov 22 Javascript
js中Object.create实例用法详解
Oct 05 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也可以?成Shell Script
2006/10/09 PHP
PHP中文URL编解码(urlencode()rawurlencode()
2010/07/03 PHP
php实现的一个很好用HTML解析器类可用于采集数据
2013/09/23 PHP
PHPExcel在linux环境下导出报500错误的解决方法
2017/01/26 PHP
thinkPHP和onethink微信支付插件分享
2019/08/11 PHP
javascript:void(0)是什么意思示例介绍
2013/11/17 Javascript
NodeJS使用jQuery选择器操作DOM
2015/02/13 NodeJs
JS实现的简洁二级导航菜单雏形效果
2015/10/13 Javascript
Javascript中匿名函数的调用与写法实例详解(多种)
2016/01/26 Javascript
JavaScript中有关一个数组中最大值和最小值及它们的下表的输出的解决办法
2016/07/01 Javascript
Bootstrap实现带动画过渡的弹出框
2016/08/09 Javascript
详解js的事件处理函数和动态创建html标记方法
2016/12/16 Javascript
angularjs利用directive实现移动端自定义软键盘的示例
2017/09/20 Javascript
vue微信分享到朋友圈 vue微信发送给好友
2018/11/28 Javascript
ES6 Object属性新的写法实例小结
2019/06/25 Javascript
jquery实现抽奖功能
2020/10/22 jQuery
python使用PyGame模块播放声音的方法
2015/05/20 Python
Python实现二叉堆
2016/02/03 Python
浅析Python编写函数装饰器
2016/03/18 Python
Python3使用requests发闪存的方法
2016/05/11 Python
python下如何查询CS反恐精英的服务器信息
2017/01/17 Python
Python中import机制详解
2017/11/14 Python
python实现简易通讯录修改版
2018/03/13 Python
Python操作MySQL数据库的两种方式实例分析【pymysql和pandas】
2019/03/18 Python
numpy数组之存取文件的实现示例
2019/05/24 Python
对python特殊函数 __call__()的使用详解
2019/07/02 Python
python获取Linux发行版名称
2019/08/30 Python
Python基本语法之运算符功能与用法详解
2019/10/22 Python
python Django 反向访问器的外键冲突解决
2020/05/20 Python
python实现测试工具(一)——命令行发送get请求
2020/10/19 Python
python的setattr函数实例用法
2020/12/16 Python
Bandier官网:奢侈、时尚前卫的健身服装首选目的地
2020/07/05 全球购物
医学护理毕业生自荐信
2013/11/07 职场文书
党的生日活动方案
2014/08/15 职场文书
小学新教师个人总结
2015/02/05 职场文书
默认网关不可用修复后过一会又不好使了解决方法
2022/04/08 数码科技