分析了一下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 相关文章推荐
jQuery控制iFrame(实例代码)
Nov 19 Javascript
利用javascript实现禁用网页上所有文本框,下拉菜单,多行文本域
Dec 14 Javascript
jQuery实现的在线答题功能
Apr 12 Javascript
解析Node.js基于模块和包的代码部署方式
Feb 16 Javascript
jQuery 判断是否包含在数组中Array[]的方法
Aug 03 Javascript
Angular2内置指令NgFor和NgIf详解
Aug 03 Javascript
layui选项卡效果实现代码
May 19 Javascript
微信小程序开发教程之增加mixin扩展
Aug 09 Javascript
js循环map 获取所有的key和value的实现代码(json)
May 09 Javascript
vue 引用自定义ttf、otf、在线字体的方法
May 09 Javascript
VUE兄弟组件传值操作实例分析
Oct 26 Javascript
VUE项目实现主题切换的多种方法
Nov 26 Vue.js
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
非洲第一个咖啡超凡杯大赛承办国—卢旺达的咖啡怎么样
2021/03/03 咖啡文化
如何阻止网站被恶意反向代理访问(防网站镜像)
2014/03/18 PHP
PHP魔术方法之__call与__callStatic使用方法
2017/07/23 PHP
PHP简单实现图片格式转换(jpg转png,gif转png等)
2019/10/30 PHP
Git命令之分支详解
2021/03/02 PHP
Jquery 实现表格颜色交替变化鼠标移过颜色变化实例
2013/08/28 Javascript
jquery实现简单易懂的图片展示小例子
2013/11/21 Javascript
jQuery简单图表peity.js使用示例
2014/05/02 Javascript
两个多选select(multiple左右)添加、删除选项和取值实例
2014/05/12 Javascript
浅谈下拉菜单中的Option对象
2015/05/10 Javascript
JS+CSS实现带小三角指引的滑动门效果
2015/09/22 Javascript
浅谈JavaScript中的对象及Promise对象的实现
2015/11/15 Javascript
微信小程序 wx.login解密出现乱码的问题解决办法
2017/03/10 Javascript
JavaScript创建对象的七种方式(推荐)
2017/06/26 Javascript
vue如何获取点击事件源的方法
2017/08/10 Javascript
Angular实现点击按钮后在上方显示输入内容的方法
2017/12/27 Javascript
Vue的事件响应式进度条组件实例详解
2018/02/04 Javascript
Vue与Node.js通过socket.io通信的示例代码
2018/07/25 Javascript
vue props 单项数据流实例分享
2020/02/16 Javascript
JS script脚本中async和defer区别详解
2020/06/24 Javascript
深入浅析python继承问题
2016/05/29 Python
python3+PyQt5重新实现自定义数据拖放处理
2018/04/19 Python
Python 在字符串中加入变量的实例讲解
2018/05/02 Python
python实现决策树ID3算法的示例代码
2018/05/30 Python
PyCharm 2020.2 安装详细教程
2020/09/25 Python
大学生毕业自荐信
2013/10/10 职场文书
大学毕业生个人自荐信范文
2014/01/08 职场文书
党员服务承诺书
2014/05/28 职场文书
青年文明号口号
2014/06/17 职场文书
工作目标责任书
2014/07/23 职场文书
五四青年节的活动方案
2014/08/20 职场文书
在职证明书范本(2014新版)
2014/09/25 职场文书
技术入股合作协议书
2014/10/07 职场文书
2014年移动公司工作总结
2014/12/08 职场文书
在职证明格式样本
2015/06/15 职场文书
家属联谊会致辞
2015/07/31 职场文书