对jQuery.extend()方法的分析

jQuery.extend方法是我们常用的方法,也是jQuery源码中的基础方法。它的主要作用是:将一个或多个“源对象”合并到一个“目标对象”中,并返回目标对象。它主要有三种表现形式:

a、jQuery.extend(destination, source1, source2, source3 ....)

b、jQuery.extend( source )

c、jQuery.extend(boolean, destination, source1, source2, source3 ....)

a方式第一个参数作为“目标对象”,其它参数作为“源对象”。

b方式只有一个参数,这里的这个参数变成了“源对象”,“目标对象”变成了jQuery。说白了就是"源对象"的属性,变成jQuery函数的静态方法或属性。

c方式的第一个参数是boolean类型的,第二个参数是"目标对象",剩下的参数是“源对象”。当第一个参数的值为true时,表示对象合并时支持“深拷贝”。

知道了函数的用法,我们肯定好奇jQuery是怎么实现的,想看看jQuery的源码。不过在看jQuery源码之前,我们不妨试着写写这个方法的功能,然后在回过头来看jQuery源码,感受可能更深,看到的东西可能越多。

我们先不要给自己压力,先从最简单的开始,要实现的方法就两个参数:第一个参数是:“目标对象”,第二个参数是:“源对象”。先实现把“源对象”合并到“目标对象”中。代码如下:

var Test = function(){}
Test.extend0 = function(destination, source){
    for(var key in source){
        destination[key] = source[key]
    }
    return destination
}

第二步实现可以传入多个参数,第一个参数是目标对象,其他参数是源对象。代码如下:

Test.extend1 = function(){
    var destination = arguments[0]
    var sourceArr = Array.prototype.slice.call(arguments,1)
    for(var i = 0, len = sourceArr.length; i < len; i++){
        var source = sourceArr[i]
        for(var key in source){
            destination[key] = source[key]
        }
    }
    return destination
}

第三步实现只有一个参数时,将参数对象的属性附加给Test。代码如下:

Test.extend2 = function(){
    var argumentsLen = arguments.length
    if( argumentsLen === 1 ){
        var source = arguments[0]
        for(var key in source){
            Test[key] = source[key]
        }
    }else{
        var destination = arguments[0]
        var sourceArr = Array.prototype.slice.call(arguments,1)
        for(var i = 0, len = sourceArr.length; i < len; i++){
            var source = sourceArr[i]
            for(var key in source){
                destination[key] = source[key]
            }
        }
        return destination
    }
}

第四步实现“深拷贝”,第一个参数是是否进行深拷贝的布尔判断,第二个参数是目标对象,其他参数是源对象。代码如下:

Test.extend3 = function(){
    var argumentsLen = arguments.length
    if( argumentsLen === 1 ){
        var source = arguments[0]
        for(var key in source){
            Test[key] = source[key]
        }
    }else{
        var firstItem = arguments[0]
        var isBoolean = typeof firstItem === "boolean"
        var destination = isBoolean ? arguments[1] : firstItem
        var startNum = isBoolean ? 2 : 1
        var sourceArr = Array.prototype.slice.call(arguments,startNum)
        for(var i = 0, len = sourceArr.length; i < len; i++){
            var source = sourceArr[i]
            if( isBoolean ){
                deepExtend( destination, source )
            }else{
                for(var key in source){
                    destination[key] = source[key]
                }
            }
        }
        return destination
    }
}

function deepExtend(destination, source){
    for(var key in source){
        var value = source[key]
        if( value instanceof Array ){
            destination[key] = arguments.callee.call( destination[key] || [], value )
        }else if( value instanceof Object ){
            destination[key] = arguments.callee.call( destination[key] || {}, value )
        }else{
            destination[key] = source[key]
        }
    }
    return destination
}

好了,我们按照自己的思路,粗略的实现了自己的extend方法,现在就看下jQuery对extend的实现,对比学习一下。源码如下:

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

    // Handle a deep copy situation
    if ( typeof target === "boolean" ) {
        deep = target;

        // skip the boolean and the target
        target = arguments[ i ] || {};
        i++;
    }

    // Handle case when target is a string or something (possible in deep copy)
    if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
        target = {};
    }

    // extend jQuery itself if only one argument is passed
    if ( i === length ) {
        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;
                }

                // Recurse if we‘re merging plain objects or arrays
                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 : {};
                    }

                    // Never move original objects, clone them
                    target[ name ] = jQuery.extend( deep, clone, copy );

                // Don‘t bring in undefined values
                } else if ( copy !== undefined ) {
                    target[ name ] = copy;
                }
            }
        }
    }

    // Return the modified object
    return target;
}

通过对比,我们发现:

a、jQuery在代码组织和实现上更加优雅。

b、jQuery考虑到了一些特殊情况。比如:

if ( target === copy ) {
      continue;
}

这是为了避免无限循环,“源对象”的属性指向的是“目标对象”,当合并对象时,也就是将“自己”复制为“自己的属性”。这是不可取的。

c、jQuery在数组(jQuery.isArray)和“纯粹对象”(jQuery.isPlainObject)的判断上,考虑的更精细。

先自己想思路去实现,再反过来对比学习,这种学习方法感觉挺好的。a、加强了独立思考能力。b、发现新的学习内容。c、暴漏自己的不足。

时间: 2024-11-05 19:28:45

对jQuery.extend()方法的分析的相关文章

jQuery extend方法使用及实现

一.jQuery extend方法介绍 jQuery的API手册中,extend方法挂载在jQuery和jQuery.fn两个不同对象上方法,但在jQuery内部代码实现的是相同的,只是功能却不太一样: 且看官方给出解释: jQuery.extend(): Merge the contents of two or more objects together into the first object.(把两个或者更多的对象合并到第一个当中): jQuery.fn.extend():Merge t

jQuery.extend() 源码分析

jQuery.extend() 方法 可以合并对象 深拷贝与浅拷贝 源码分析: 概述:  1. 首先定义变量 options:保存每次循环遍历的arguments[i] , name: 保存循环遍历对象的key值 src:保存目标对象target的属性 copy: 保存合并对象的属性 copyIsArray: 如果copy是数组,用copyIsArray保存 clone:如果目标对象是数组,用clone保存. target:目标对象 deep: boolean值,判断是否是深拷贝 2. 然后判断

jQuery.extend方法和开发中变量的复用

最近在用commonJS规范进行客户端开发,遇到如下问题: 一般一个模块内部可能会定义一系列变量或一系列相关变量,比如写了一个颜色选择弹框模块大概会有如下变量定义 var settings = { //设置它是否绝对定位 position: { //定位可以是绝对定位,可以是相对定位(需要有target),也可以是默认定位 type: "none", top: 30, left: 30, //表示相对于目标的定位 target: "", zindex: 0 }, /

jquery.extend方法

jquery.extend()用来扩展jquery中方法,实现插件. 1.jQuery.extend函数详细用法! 扩展jQuery静态方法. 1$.extend({2test:function(){alert('test函数')}3}) 用法: $.test() 2.jQuery.extend 函数详解 上述两个虽说叫详解,讲解都很简略,下面这篇好一点. 3.jQuery $.extend()用法总结 jQuery.extend(object);为扩展jQuery类本身.为类添加新的方法. j

jQuery extend方法介绍

jQuery为开发插件提拱了两个方法,分别是: jQuery.fn.extend(object); jQuery.extend(object); jQuery.extend(object);为扩展jQuery类本身.为类添加新的方法. jQuery.fn.extend(object);给jQuery对象添加方法.这个应该很好理解吧.举个例子. 1.合并多个对象. 这里使用的就是$.extend()的嵌套多个对象的功能. 所谓嵌套多个对象,有点类似于数组的合并的操作. <span style=&quo

Jquery extend() 方法

Jquery 中$.extend() 方法用于实现合并多个对象的属性到第一个对象中. $.extend(object1, [object2] ); 将后两个对象即object1和object2中的属性合并到object1中,默认是合并覆盖操作,不进行迭代. 此时object1 对object2 的拷贝为浅拷贝(公用一份实体,仅仅是引用变量不同) <script type="text/javascript"> obj1 = {a: "this is a",

对jQuery.isArray方法的分析

jQuery.isArray方法应于判断是不是数组,是的话返回true,否则返回false.调用如:jQuery.isArray([]),返回true.其实现源码如下: isArray: Array.isArray || function( obj ) { return jQuery.type(obj) === "array"; } 我们看到它的主要逻辑是先看浏览器支不支持Array.isArray方法,如果不支持则调应jQuery自己的jQuery.type方法,看其返回值是不是&q

jQuery extend方法使用

  $(function () { var object1 = { apple: 0, banana: {weight: 52, price: 100}, cherry: 97 }; var object2 = { banana: {price: 200}, durian: 100 }; /* object2 合并到 object1 中 */ $.extend(object1, object2); /*判断是否存在对象如果有则直接调用该对象将普通对象转换成json数据 否则创建一个函数用于讲普通

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对象