分析了一下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 相关文章推荐
有关JavaScript的10个怪癖和秘密分享
Aug 28 Javascript
D3.js 从P元素的创建开始(显示可加载数据)
Oct 30 Javascript
director.js实现前端路由使用实例
Feb 03 Javascript
了解Javascript的模块化开发
Mar 02 Javascript
JS中的THIS和WINDOW.EVENT.SRCELEMENT详解
May 25 Javascript
Javascript中函数名.length属性用法分析(对比arguments.length)
Sep 16 Javascript
JS将unicode码转中文方法
May 08 Javascript
Vue.js中轻松解决v-for执行出错的三个方案
Jun 09 Javascript
vue系列之动态路由详解【原创】
Sep 10 Javascript
layui 优化button按钮和弹出框的方法
Aug 15 Javascript
vue路由跳转传递参数的方式总结
May 10 Javascript
解决qrcode.js生成二维码时必须定义一个空div的问题
Jul 09 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修改session_id示例代码
2014/01/08 PHP
CI框架中通过hook的方式实现简单的权限控制
2015/01/07 PHP
JavaScript Object的extend是一个常用的功能
2009/12/02 Javascript
jquery实现的用户注册表单提示操作效果代码分享
2015/08/28 Javascript
Bootstrap每天必学之简单入门
2015/11/19 Javascript
基于JavaScript实现动态创建表格和增加表格行数
2015/12/20 Javascript
利用css+原生js制作简单的钟表
2020/04/07 Javascript
基于jQuery实现歌词滚动版音乐播放器的代码
2016/09/17 Javascript
深入理解Node.js 事件循环和回调函数
2016/11/02 Javascript
详解js运算符单竖杠“|”与“||”的用法和作用介绍
2016/11/04 Javascript
详解nodejs 文本操作模块-fs模块(四)
2016/12/22 NodeJs
基于JavaScript实现自定义滚动条
2017/01/25 Javascript
Vue监听数组变化源码解析
2017/03/09 Javascript
angularjs下ng-repeat点击元素改变样式的实现方法
2018/09/12 Javascript
Vue动态创建注册component的实例代码
2019/06/14 Javascript
解决vuex刷新数据消失问题
2020/11/12 Javascript
微信小程序实现电影App导航和轮播
2020/11/30 Javascript
python中sys.argv参数用法实例分析
2015/05/20 Python
python开发之字符串string操作方法实例详解
2015/11/12 Python
python结合shell查询google关键词排名的实现代码
2016/02/27 Python
python爬虫爬取快手视频多线程下载功能
2018/02/28 Python
python实现寻找最长回文子序列的方法
2018/06/02 Python
Python+selenium 获取一组元素属性值的实例
2018/06/22 Python
对python中if语句的真假判断实例详解
2019/02/18 Python
Django 过滤器汇总及自定义过滤器使用详解
2019/07/19 Python
基于python的docx模块处理word和WPS的docx格式文件方式
2020/02/13 Python
基于Python编写一个计算器程序,实现简单的加减乘除和取余二元运算
2020/08/05 Python
Python用来做Web开发的优势有哪些
2020/08/05 Python
使用HTML5的File实现base64和图片的互转
2013/08/01 HTML / CSS
荷兰皇家航空公司中国官网:KLM中国
2017/12/13 全球购物
社会学专业求职信
2014/07/17 职场文书
支行行长岗位职责
2015/02/15 职场文书
经营目标责任书
2015/05/08 职场文书
《比的意义》教学反思
2016/02/18 职场文书
Python中os模块的简单使用及重命名操作
2021/04/17 Python
MySQL表字段时间设置默认值
2021/05/13 MySQL