`
helloworld1987
  • 浏览: 5214 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

jQuery源码分析-extend函数

阅读更多
准备将jQuery、Ext等框架源码仔细分析一遍,并将结果发出来供大家学习、讨论。
这是我的处女贴,请大家多多关照!

/*!
 * jQuery源码分析-extend函数
 * jQuery版本:1.4.2
 * 
 * ----------------------------------------------------------
 * 函数介绍
 * jQuery.extend与jQuery.fn.extend指向同一个函数对象
 * jQuery.extend是jQuery的属性函数(静态方法)
 * jQuery.fn.extend是jQuery函数所构造对象的属性函数(对象方法)
 *
 * ----------------------------------------------------------
 * 使用说明
 * extend函数根据参数和调用者实现功能如下:
 * 1.对象合并:
 * 对象合并不区分调用者,jQuery.extend与jQuery.fn.extend完全一致
 * 也就是说对jQuery对象本身及jQuery所构造的对象没有影响
 * 对象合并根据参数区分,参数中必须包括两个或两个以上对象
 * 如:$.extend({Object}, {Object}) 或 $.extend({Boolean},{Object}, {Object})
 * 对象合并返回最终合并后的对象,支持深度拷贝
 * 
 * 2.为jQuery对象本身增加方法:
 * 这种方式从调用者和参数进行区分
 * 形式为 $.extend({Object})
 * 这种方式等同于 jQuery.{Fnction Name}
 * 
 * 3.原型继承:
 * 原型继承方式可以为jQuery所构造的对象增加方法
 * 这种方式也通过调用者和参数进行区分
 * 形式为 $.fn.extend({Object})
 * 这种方式实际上是将{Object}追加到jQuery.prototype,实现原型继承
 * 
 * ----------------------------------------------------------
 * 
 */
 
// jQuery.fn = jQuery.prototype
// jQuery.fn.extend = jQuery.prototype.extend
jQuery.extend = jQuery.fn.extend = function(){

    //目标对象
    var target = arguments[0] || {},    
    
    //循环变量,它会在循环时指向需要复制的第一个对象的位置,默认为1
    //如果需要进行深度复制,则它指向的位置为2
    i = 1,    
    
    //实参长度
    length = arguments.length,    
    
    //是否进行深度拷贝
    //深度拷贝情况下,会对对象更深层次的属性对象进行合并和覆盖
    deep = false,    
    
    //用于在复制时记录参数对象
    options,    
    
    //用于在复制时记录对象属性名
    name,    
    
    //用于在复制时记录目标对象的属性值
    src,    
    
    //用于在复制时记录参数对象的属性值
    copy;
    
    //只有当第一个实参为true时,即需要进行深度拷贝时,执行以下分支
    if (typeof target === "boolean") {
        //deep = true,进行深度拷贝
        deep = target;
        
        //进行深度拷贝时目标对象为第二个实参,如果没有则默认为空对象
        target = arguments[1] || {};
        
        //因为有了deep深度复制参数,因此i指向的位置为第二个参数
        i = 2;
    }
    
    //当目标对象不是一个Object且不是一个Function时(函数也是对象,因此使用jQuery.isFunction进行检查)
    if (typeof target !== "object" && !jQuery.isFunction(target)) {
        
        //设置目标为空对象
        target = {};
    }
    
    //如果当前参数中只包含一个{Object}
    //如 $.extend({Object}) 或 $.extend({Boolean}, {Object})
    //则将该对象中的属性拷贝到当前jQuery对象或实例中
    //此情况下deep深度复制仍然有效
    if (length === i) {
        
        //target = this;这句代码是整个extend函数的核心
        //在这里目标对象被更改,这里的this指向调用者
        //在 $.extend()方式中表示jQuery对象本身
        //在 $.fn.extend()方式中表示jQuery函数所构造的对象(即jQuery类的实例)
        target = this;
        
        //自减1,便于在后面的拷贝循环中,可以指向需要复制的对象
        --i;
    }
	
	//循环实参,循环从第1个参数开始,如果是深度复制,则从第2个参数开始
    for (; i < length; i++) {
        
        //当前参数不为null,undefined,0,false,空字符串时
        //options表示当前参数对象
        if ((options = arguments[i]) != null) {
            
            //遍历当前参数对象的属性,属性名记录到name
            for (name in options) {
                
                //src用于记录目标对象中的当前属性值
                src = target[name];
                
                //copy用于记录参数对象中的当前属性值
                copy = options[name];
                
                //存在目标对象本身的引用,构成死循环,结束此次遍历
                if (target === copy) {
                    continue;
                }
                
                //如果需要进行深度拷贝,且copy类型为对象或数组
                if (deep && copy && (jQuery.isPlainObject(copy) || jQuery.isArray(copy))) {
                
                    //如果src类型为对象或数组,则clone记录src
                    //否则colne记录与copy类型一致的空值(空数组或空对象)
                    var clone = src && (jQuery.isPlainObject(src) || jQuery.isArray(src)) ? src : jQuery.isArray(copy) ? [] : {};
                    
                    //对copy迭代深度复制
                    target[name] = jQuery.extend(deep, clone, copy);
                    
                    //如果不需要进行深度拷贝
                } else if (copy !== undefined) {
                    
                    //直接将copy复制给目标对象
                    target[name] = copy;
                }
            }
        }
    }
    
    //返回处理后的目标对象
    return target;
};


/**
 * jQuery框架本身对extend函数的使用非常频繁
 * 典型示例为jQuery.ajax
 * 
 */

//使用extend对jQuery对象本身进行扩展,只给了一个参数对象
//该对象中的属性将被追加到jQuery对象中
jQuery.extend({
 
    //jQuery.ajax
    //$.ajax
 
    //这里的origSettings参数是自定义的ajax配置
    //jQuery对象本身有一个ajaxSettings属性,是默认的ajax配置
    ajax: function(origSettings){ 
 
        //这里使用extend对ajax配置项进行合并
        //第一个参数表示进行深度拷贝
        //首先将第3个参数jQuery.ajaxSettings(即jQuery默认ajax配置)复制到第2个参数(一个空对象)
        //然后将第4个参数(自定义配置)复制到配置对象(覆盖默认配置)
        //这里的s就得到了最终的ajax配置项
        var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings);
  
        //其它相关代码...(省略)
    }
}); 
分享到:
评论
16 楼 Fonkie 2010-12-26  
分析得挺不错的,读懂熟透JQuery的源码,是开发插件的前提。
15 楼 zhangqh_zz 2010-07-26  
感谢楼主的奉献,
分析写得很好,谢谢
14 楼 lybykw 2010-07-22  
分析得太详细了,期待更多分析
13 楼 helloworld1987 2010-07-22  
adamed 写道
稍微为楼主补充几句:
#     if (length === i) { 
#         target = this; 
#         --i; 
#     } 

上面的代码,为什么要有这句?楼主的注释意思上是没问题的,关键是为啥要这样写。
在jQuery的API文档上我们可以看到。extend作用是扩展对象,并且有专门一个地方说明可以用来扩展jQuery本身。
比如:
jQuery.extend({
  min: function(a, b) { return a < b ? a : b; },
  max: function(a, b) { return a > b ? a : b; }
});
表示向jQuery中添加2个方法插件。
再比如:
jQuery 代码:
var settings = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };
jQuery.extend(settings, options);
结果:
settings == { validate: true, limit: 5, name: "bar" }
这里就是拓展普通对象了。

那么如何区分哪个调用是扩展jQuery本身,哪个是扩展普通对象呢?
就看这个if是否为true,如果为true则target=this也就表示拓展jQuery本身。否则就是扩展普通对象

这里的确没有注释清楚,有待改善。
谢谢指教。
12 楼 adamed 2010-07-22  
稍微为楼主补充几句:
#     if (length === i) { 
#         target = this; 
#         --i; 
#     } 

上面的代码,为什么要有这句?楼主的注释意思上是没问题的,关键是为啥要这样写。
在jQuery的API文档上我们可以看到。extend作用是扩展对象,并且有专门一个地方说明可以用来扩展jQuery本身。
比如:
jQuery.extend({
  min: function(a, b) { return a < b ? a : b; },
  max: function(a, b) { return a > b ? a : b; }
});
表示向jQuery中添加2个方法插件。
再比如:
jQuery 代码:
var settings = { validate: false, limit: 5, name: "foo" };
var options = { validate: true, name: "bar" };
jQuery.extend(settings, options);
结果:
settings == { validate: true, limit: 5, name: "bar" }
这里就是拓展普通对象了。

那么如何区分哪个调用是扩展jQuery本身,哪个是扩展普通对象呢?
就看这个if是否为true,如果为true则target=this也就表示拓展jQuery本身。否则就是扩展普通对象
11 楼 helloworld1987 2010-07-22  
adamed 写道
#  //只有当第一个实参为true时,即需要进行深度拷贝时,执行以下分支 
#     if (typeof target === "boolean") { 

这一句应该只是说判断target类型是否为boolean值。
就算target为false 这个if也是能通过的。

验证:alert(typeof false==='boolean'); 打印true

回ls:
从语义上看起来,这句代码是检查boolean类型的。
但再看看函数的第一句代码:
var target = arguments[0] || {}
当第一个参数为false时,target是{},而不是boolean;
因此,只有当第一个参数为true时才会执行。
所以这个分支也可以改为
if(true === target) {
    //其它代码...
}
10 楼 adamed 2010-07-22  
#  //只有当第一个实参为true时,即需要进行深度拷贝时,执行以下分支 
#     if (typeof target === "boolean") { 

这一句应该只是说判断target类型是否为boolean值。
就算target为false 这个if也是能通过的。

验证:alert(typeof false==='boolean'); 打印true
9 楼 gogole_09 2010-07-22  
helloworld1987 写道
Quen 写道
看来有点深度,哥们,能不能结合一些例子!这似乎更易理解些吧!

我想没有比源码更好的例子了,如果这也不容易理解的话,看来是我注释的还不够清楚。。。

  首先赞LZ的精神。另:我想ls是希望先从extend函数的使用开始说起,然后结合例子来深入解析源代码,若能总结出源代码中的技巧和好处的话,相信会印象更加深刻。
8 楼 helloworld1987 2010-07-21  
Quen 写道
看来有点深度,哥们,能不能结合一些例子!这似乎更易理解些吧!

我想没有比源码更好的例子了,如果这也不容易理解的话,看来是我注释的还不够清楚。。。
7 楼 Quen 2010-07-21  
看来有点深度,哥们,能不能结合一些例子!这似乎更易理解些吧!
6 楼 lioncin 2010-07-21  
lz v5
5 楼 helloworld1987 2010-07-20  
感谢大家鼓励!我会将jQuery源码全部分析注释一遍,和大家一起学习讨论。
4 楼 dhgdmw 2010-07-20  
恩,不错,jQuery一直在用,可没时间看源码,改天倡议下每人贡献个函数分析,免得各自分析时费时费力
3 楼 hrsvici412 2010-07-20  
楼主辛苦了,学习榜样,支持你!
2 楼 trace 2010-07-20  
楼上的,读源码是最有效的学习方式,难得楼主写出这么详细的注释。你一句话说出来,除了能把它用好,还能学到什么?

简单这个概念是面对用户的,做程序员的在学习上可不能对自己要求“简单”。只知其表而不知其里的人,永远只能做coder,永远只能跟在技术的屁股后面;只有深入了解了你用的技术,才能算是programmer。

鼓励楼主写出更多的源码分析,加油!
1 楼 kgd924 2010-07-19  
现在的人都很喜欢简单的,最好一句话就把Extend的原理说清楚了。

我觉得Javascript所谓的extends就是把父类的属性,复制到子类。

相关推荐

    jQuery源码分析-03构造jQuery对象

    ### jQuery源码分析—构造jQuery对象 #### 一、源码结构概览 根据所提供的文件内容,本节将深入分析如何构建jQuery对象及其核心构造逻辑。首先,让我们从整体上理解jQuery构造函数的设计思路。 ##### 总体结构 ...

    139.jQuery源码分析-魔术方法.rar

    《jQuery源码分析——魔术方法》 jQuery,作为一款广泛使用的JavaScript库,以其简洁的API和强大的功能赢得了开发者们的喜爱。在深入理解jQuery的工作原理时,我们常常会遇到一些“魔术方法”,这些方法在特定场景...

    jQuery-, jQuery源码解读 -- jQuery v1.10.2.zip

    源码分析可以让我们理解jQuery如何使用CSS属性和时间函数实现平滑的动画效果。 7. **插件扩展机制** jQuery的插件系统是其灵活性的关键。通过研究`$.fn.extend()`和`$.extend()`,我们可以学习如何编写自己的...

    Jquery源码分析 源码

    《jQuery源码分析》 jQuery,作为一款广泛使用的JavaScript库,极大地简化了DOM操作、事件处理、动画制作以及Ajax交互。深入理解其源码对于提升JavaScript编程技能和优化前端性能至关重要。本文将从核心概念、设计...

    jQuery源码分析-03构造jQuery对象-源码结构和核心函数

    在进行jQuery源码分析的过程中,我们了解到jQuery对象是通过内部函数`jQuery.fn.init`构造的,其方法和属性则通过原型链继承自`jQuery.fn`,这是jQuery能够提供丰富且灵活DOM操作方法的基石。通过这种方式,即使不...

    jQuery源码分析(1.7)

    ### jQuery源码分析关键知识点详解 #### 一、前言 在深入了解jQuery源码之前,有必要先简要介绍一下jQuery的基本情况及其对JavaScript编程领域的重要意义。jQuery作为一个轻量级、功能丰富的JavaScript库,在Web...

    JQuery源码详细中文注释_Jquery源码分析_

    总结,jQuery源码分析涉及的内容广泛,包括选择器引擎、事件处理、DOM操作、动画效果、Ajax通信以及插件开发等多个方面。深入理解jQuery源码,有助于我们更好地利用它来构建高效、易维护的Web应用。通过阅读中文注释...

    jquery-source-code-analysis:jquery源码分析-jquery source code

    《jQuery源码分析——深入理解其机制》 jQuery,作为一款广泛使用的JavaScript库,极大地简化了DOM操作、事件处理和Ajax交互。对于任何想要提升JavaScript技能的开发者来说,理解jQuery的源码是至关重要的一步。...

    Jquery详解-源码分析

    提供的压缩包文件名列表与Jquery源码分析的主题不相符,它们看起来是音频文件的名称,可能是相声或者音乐作品。然而,你要求的是关于Jquery的源码分析。因此,我将专注于Jquery这个JavaScript库的相关知识点。 **...

    jquery-source-code-1:jquery源码-jquery source code

    jquery源码分析(2.0.3版本) 大概内容大纲 (功能(){ (21,94)定义了一些变量和函数jQuery = function(){} (96,284)给JQ对象添加一些方法和属性 (285,347)扩展名:JQ的继承方法 (349,817)jQuery....

    我的第一个jQuery插件 -- 圆角DIV

    **源码分析**: 通过查看`round.js`,我们可以学习如何编写自定义的jQuery插件,包括如何接收参数,如何处理DOM元素,以及如何结合CSS样式来实现特定的视觉效果。同时,`round.html`可以作为实例来理解如何在实际...

    jQuery-sound-code:jQuery源码分析

    《jQuery源码分析》 jQuery,作为一款广泛使用的JavaScript库,极大地简化了DOM操作、事件处理、动画制作以及Ajax交互。本项目旨在深入解析jQuery的源码,通过分段解析、添加全中文注释和制作成手册的方式,帮助...

    jQuery-Source-code-analysis-.rar_code

    《jQuery源码分析》 jQuery,作为一款广泛应用于前端开发的JavaScript库,以其简洁的API、高效的DOM操作和丰富的插件系统,极大地提升了开发者的工作效率。深入理解jQuery的源码,不仅能帮助我们更好地运用它,还能...

    Jquery-source-code.zip_code

    《jQuery源码解析:深入理解JavaScript库之精髓》 jQuery,作为一款广泛应用于Web开发的JavaScript库,以其简洁、易用的API深受开发者喜爱。它极大地简化了DOM操作、事件处理、动画效果以及Ajax交互等任务,使得...

    jQuery 源码分析最新1.2.6

    【jQuery 源码分析最新1.2.6】 jQuery 是一个高效、简洁的JavaScript库,专注于DOM操作、事件处理、Ajax交互以及动画效果。在深入理解jQuery的源码时,我们可以从以下几个核心概念出发: 1. **jQuery对象与DOM元素...

Global site tag (gtag.js) - Google Analytics