分析了一下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 相关文章推荐
中文路径导致unitpngfix.js不正常的解决方法
Jun 26 Javascript
Jquery 实现checkbox全选方法
Jan 28 Javascript
JQuery中基础过滤选择器用法实例分析
May 18 Javascript
ECMAScript6函数剩余参数(Rest Parameters)
Jun 12 Javascript
JS实现网页上随机产生超链接地址的方法
Nov 09 Javascript
深入解析AngularJS框架中$scope的作用与生命周期
Mar 05 Javascript
javascript数组对象常用api函数小结(连接,插入,删除,反转,排序等)
Sep 20 Javascript
Angular 4.X开发实践中的踩坑小结
Jul 04 Javascript
vue resource post请求时遇到的坑
Oct 19 Javascript
微信小程序实现元素渐入渐出动画效果封装方法
May 18 Javascript
Vue.js中的组件系统
May 30 Javascript
vue实现学生信息管理系统
May 30 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/11/25 PHP
从PHP $_SERVER相关参数判断是否支持Rewrite模块
2013/09/26 PHP
PHP关于htmlspecialchars、strip_tags、addslashes的解释
2014/07/04 PHP
php读取mssql的ntext字段返回值为空的解决方法
2014/12/30 PHP
PHP实现根据图片色界在不同位置加水印的方法
2015/08/08 PHP
jQuery选择没有colspan属性的td的代码
2010/07/06 Javascript
Jquery异步请求数据实例代码
2011/12/28 Javascript
JavaScript高级程序设计(第3版)学习笔记5 js语句
2012/10/11 Javascript
JS格式化数字保留两位小数点示例代码
2013/10/15 Javascript
JQuery包裹DOM节点的方法
2015/06/11 Javascript
Laravel中常见的错误与解决方法小结
2016/08/30 Javascript
bootstrap PrintThis打印插件使用详解
2017/02/20 Javascript
深入理解Node.js中通用基础设计模式
2017/09/19 Javascript
ES6学习教程之块级作用域详解
2017/10/09 Javascript
npm全局模块卸载及默认安装目录修改方法
2018/05/15 Javascript
bootstrap与pagehelper实现分页效果
2018/12/29 Javascript
node.js中process进程的概念和child_process子进程模块的使用方法示例
2020/02/11 Javascript
Vue watch响应数据实现方法解析
2020/07/10 Javascript
JavaScript JSON使用原理及注意事项
2020/07/30 Javascript
[01:00:59]VP VS VG Supermajor小组赛胜者组第二轮 BO3第二场 6.2
2018/06/03 DOTA
python实现类的静态变量用法实例
2015/05/08 Python
Python中字典映射类型的学习教程
2015/08/20 Python
python实现决策树分类算法
2017/12/21 Python
python3 selenium 切换窗口的几种方法小结
2018/05/21 Python
从django的中间件直接返回请求的方法
2018/05/30 Python
查看TensorFlow checkpoint文件中的变量名和对应值方法
2018/06/14 Python
解决Pycharm运行时找不到文件的问题
2018/10/29 Python
在python中画正态分布图像的实例
2019/07/08 Python
Crocs卡骆驰洞洞鞋日本官方网站:Crocs日本
2016/08/25 全球购物
益模软件Java笔试题
2012/03/27 面试题
数据库面试要点基本概念
2013/10/31 面试题
高级护理实习生自荐信
2013/09/28 职场文书
2014年最新学习全国两会精神心得
2014/03/17 职场文书
销售内勤岗位职责范本
2015/04/13 职场文书
Python实战之实现简易的学生选课系统
2021/05/25 Python
用python基于appium模块开发一个自动收取能量的小助手
2021/09/25 Python