jquery的2.0.3版本源码系列(3):285-348行,extend方法详解

目录

1 . jquery extend的基本使用

通过285行的源码 jQuery.extend = jQuery.fn.extend = function() { ,extend方法要么是直接挂在到jQuery的静态方法,要么是挂载到fn上其实就是原型上(参考283行的赋值操作)的实例方法。extend方法可以传一个对象,类似于插件的方式,也可以传多个对象进行拷贝。

<script src="js/jquery-2.0.3.js"></script>
    <script>
        $.extend({
            aaa:function(){
                alert("1");
            },
            bbb:function(){
                alert("2");
            }
        })
        $.fn.extend({
            aaa:function(){
                alert("3");
            },
            bbb:function(){
                alert("4");
            }
        })
        $.aaa();//弹出1,静态方法可以直接调用
        $().aaa();//弹出3,绑定到fn上的方法,以对象的形式调用
        //多个对象参数,后面的对象会扩展到第一个对象上
        var a={};
        $.extend(a,{color:‘#f40‘});
        console.log(a);//color所在的对象就被扩展到a对象上
    </script>

接下来关注extend的拷贝分深拷贝和浅拷贝。

<script src="js/jquery-2.0.3.js"></script>
    <script>
        var a={};
        var b={name:"hello"};
        var c={name:"hello-1"};
        var d={name:{age:20}};
        var e={name:{age:50}};
        //浅拷贝对象b
        $.extend(a,b);
        a.name="hi";
        alert(b.name);//弹出hello
        //浅拷贝对象d
        $.extend(a,d);
        a.name.age=30;
        alert(d.name.age);//弹出30
        //深拷贝对象c
        $.extend(true,a,c);
        a.name="hi";
        alert(c.name);//弹出hello-1
        //深拷贝对象e
        $.extend(true,a,e);
        a.name.age=40;
        alert(e.name.age);//弹出50
    </script>

2.代码简化版本

分为5个部分:

定义了一些变量

if(){}  是不是深拷贝

if(){}  参数正确不

if(){}  看是不是插件的情况,插件的话传入一个含有方法的json对象

for   传入多个对象的情况

if防止循环应用,if深拷贝,else if浅拷贝。

详解篇:3.1 定义了一些变量

var options, name, src, copy, copyIsArray, clone,
        target = arguments[0] || {},
        i = 1,
        length = arguments.length,
        deep = false;

这里要说明一下target。它就是 $.extend(a,d); 拷贝的目标对象a。这里的arguments是javascript的内置对象,是一个类数组,索引为0的值当然是参数a。

详解篇:3.2 看是不是深拷贝

// 处理深拷贝的情形
    if ( typeof target === "boolean" ) {
        deep = target;
        target = arguments[1] || {};
        // 如果传入的第一个参数为true,那么deep就置为true了。target目标对象就调整为第二个。
       //跳过布尔值和target
        i = 2;
    }

这里处理的是传入了true的情况,比如 $.extend(true,a,c); 。

详解篇:3.3 要传正确的的参数

// 如果传进来的并非object同时也不是function,那么target置为空对象。
    if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
        target = {};
    }

详解篇:3.4 处理插件的情形

// 如果传进来一个参数,那么target目标对象就为jquery自己。
    if ( length === i ) {
        target = this;
        --i;
    }

详解篇:3.5 传入多个对象的操作

基本思路是通过arguments进行取值,获取到每个非目标对象的参数。非target对象通过in循环,获取到属性名。

总体特征是浅拷贝只能拷贝一层,深拷贝可以连嵌套子对象也能拷贝进去。

浅拷贝的情况下,那么走的是else分支,对相应的值进行覆盖  target[ name ] = copy; 。可以看到如果原来有target有相同的属性,那么就覆盖,如果没有,那么就添加上。

<script src="js/jquery-2.0.3.js"></script>
    <script>
        var a={name:{age:20}};
        var b={name:{age:50}};
        //浅拷贝对象b
        $.extend(false,a,b);
        console.log(a);//{name:{age:20}}
        console.log(b);//{name:{age:50}}
    </script>

它遇到对象嵌套,copy这里是{age:50},通过简单的赋值是修改不了的。

<script>
        var a={name:{age:20}};
        var b={name:{age:50}};
        a[name]=b[name];
        console.log(a);//{name:{age:20}},没有变化哦。
    </script>

深拷贝的情况下。copy是数组,src也为数组赋值给clone否则为空数组。copy是对象,src是对象赋值给clone否则为空对象。

<script src="js/jquery-2.0.3.js"></script>
    <script>
        var a={name:{age:20}};
        var b={name:{age:50}};
        //浅拷贝对象b
        $.extend(true,a,b);
        console.log(a);//{name:{age:50}}
        console.log(b);//{name:{age:50}}
    </script>

深拷贝的copy等于{age:50},src等于{age:20}。那么通过克隆的方式就可以把copy给到src。这其实是一个递归调用,所以深拷贝会拷贝到底。

for ( ; i < length; i++ ) {
        // 处理非空或者没有定义的情况
        if ( (options = arguments[ i ]) != null ) {
            // 扩展基础对象,in语法把属性值取出来
            for ( name in options ) {
                src = target[ name ];
                copy = options[ name ];

                // 防止无限循环,类似$.extend(a,{name:a})。那么如果拷贝的某一个值就等于target那么就终止代码在继续循环
                if ( target === copy ) {
                    continue;
                }

                // 深拷贝和copy存在,以及copy要么是对象、要么是数组
                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 );

                // Don‘t bring in undefined values
                } else if ( copy !== undefined ) {
                    target[ name ] = copy;
                }
            }
        }
    }
时间: 08-30

jquery的2.0.3版本源码系列(3):285-348行,extend方法详解的相关文章

jquery的2.0.3版本源码系列(1)总体结构

为什么选择2.X版本,而不是1.X版本,因为2.X不兼容IE6/7/8,所以少了兼容代码,让我们更专注于jquery原理的代码. 一共有8830行. 1.1 匿名函数自执行 首先,匿名函数的作用是,把函数内部的变量和函数变成"局部变量"和"局部函数"的,那么就不会与外部的变量和函数发生冲突了. (function(){ var a=10; })(); alert(a);//console.log报错,"Uncaught ReferenceError: a

JDK源码学习(2)-String.intern()方法详解

1.方法intern()为java内部方法,如下  public native String intern(); native方法为通过jvm进行运行,jdk8中隐藏了该方法的具体处理方法. 2.作用:该方法注释为 "如果常量池中存在当前字符串, 就会直接返回当前字符串. 如果常量池中没有此字符串, 会将此字符串放入常量池中后, 再返回". 3.测试代码一 public static void main(String[] args) { String s1 = new String(&

Linux下FFMPEG--H264--编码&&解码的C实现与相关原理详解

FFMPEG是很强大的一套视频音频处理库,不过,强大的功能一般免不了复杂的实现,或者更加现实地说,"麻烦"的部署和使用流程 关于"FFMPEG怎么部署"这事就放在另一篇文章啦,下面入正题.. 编码encoder模块和解码decoder模块都有init初始化方法和资源free方法 init初始化方法主要是进行ffmpeg所必需的编解码器的初始化和部分功能方法的参数配置,而free资源释放方法则是相应地进行必要的回收 Encoder模块的实现和细节分析 #include

Spring各版本源码下载

spring framework 各版本源码下载地址 现在spring的源码下载地址真是不好找,这次终于找到了.记录一下,以帮助需要的朋友. https://github.com/spring-projects/spring-framework/tags可以选择需要的版本进行下载. 感谢网友 xiyuan1999 在csdn上提供的此下载地址.

可解决由于IIS、VS低版本源码 兼容性问题。

安装完 Internet Information Services和 Web 管理工具 后,重启VS,以管理员身份打开,同时 选择源码--属性--安全--添加 everyone 所有权限,配置IIS,即可解决由于IIS.VS低版本源码 兼容性问题. 解决方法: 重新启动时  右键 选以管理员身份运行 那是兼容性还没配置把 控制面板-程序和功能 打开或关闭 Windows 功能 找到这个Internet Information Services 展开Web 管理工具 安装完 Internet In

Apache Spark源码走读之13 -- hiveql on spark实现详解

欢迎转载,转载请注明出处,徽沪一郎 概要 在新近发布的spark 1.0中新加了sql的模块,更为引人注意的是对hive中的hiveql也提供了良好的支持,作为一个源码分析控,了解一下spark是如何完成对hql的支持是一件非常有趣的事情. Hive简介 Hive的由来 以下部分摘自Hadoop definite guide中的Hive一章 "Hive由Facebook出品,其设计之初目的是让精通SQL技能的分析师能够对Facebook存放在HDFS上的大规模数据集进行分析和查询. Hive大大

jQuery插件开发及jQuery.extend函数详解和jQuery.fn与jQuery.prototype区别

一.jQuery插件开发分为两种:  1.类级别: 类级别你可以理解为拓展jquery类,最明显的例子是$.ajax(...),相当于静态方法. 开发扩展其方法时使用$.extend方法,即jQuery.extend(object); $.extend({ add:function(a,b){return a+b;} , minus:function(a,b){return a-b;} }); var i = $.add(3,2); var j = $.minus(3,2); 2.对象级别: 对

Jquery遍历筛选数组的几种方法和遍历解析json对象|Map()方法详解

一.Jquery遍历筛选数组 1.jquery grep()筛选遍历数组 $().ready( function(){ var array = [1,2,3,4,5,6,7,8,9]; var filterarray = $.grep(array,function(value){ return value > 5;//筛选出大于5的 }); for(var i=0;i<filterarray.length;i++){ alert(filterarray[i]); } for (key in f

jQuery.extend()、jQuery.fn.extend()扩展方法详解

jQuery自定义了jQuery.extend()和jQuery.fn.extend()方法.其中jQuery.extend()方法能够创建全局函数或者选择器,而jQuery.fn.extend()方法能够创建jQuery对象方法. 例如: jQuery.extend({ showName : function(name){ alert(name) } }); jQuery.showName("深蓝"); jQuery.extend()除了可以创建插件外,还可以用来扩展jQuery对象