zoukankan      html  css  js  c++  java
  • 解读jQuery中extend函数

    $.extend.apply( null, [ true, { "a" : 1, "b" : 2 } ] );
    //console.log(window.a);

    //window.location.reload(); $.extend.apply( null, [ true, { "a" : 1, "b" : 2 } ].concat( { "c" : 3, "d" : 4 } ) ); //console.log(window.a)

    一、问题:

      1. null在这里是干啥?

      2. window.a分别是什么?

    二、我们先一起来了解下jQuery中的extend函数

     在jQuery-V1.2.6中:

    jQuery.extend = jQuery.fn.extend = function() {
        // copy reference to target object
        var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;
    
        // Handle a deep copy situation
        if ( target.constructor == Boolean ) {
            deep = target;
            target = arguments[1] || {};
            // skip the boolean and the target
            i = 2;
        }
    
        // Handle case when target is a string or something (possible in deep copy)
        if ( typeof target != "object" && typeof target != "function" )
            target = {};
    
        // extend jQuery itself if only one argument is passed
        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 ( var name in options ) {
                    var src = target[ name ], copy = options[ name ];
    
                    // Prevent never-ending loop
                    if ( target === copy )
                        continue;
    
                    // Recurse if we're merging object values
                    if ( deep && copy && typeof copy == "object" && !copy.nodeType )
                        target[ name ] = jQuery.extend( deep, 
                            // Never move original objects, clone them
                            src || ( copy.length != null ? [ ] : { } )
                        , copy );
    
                    // Don't bring in undefined values
                    else if ( copy !== undefined )
                        target[ name ] = copy;
    
                }
    
        // Return the modified object
        return target;
    };
    jQuery - v1.2.6 extend

    在jQuery-V1.8.2中:

    jQuery.extend = jQuery.fn.extend = function() {
        var options, name, src, copy, copyIsArray, clone,
            target = arguments[0] || {},
            i = 1,
            length = arguments.length,
            deep = false;
    
        // Handle a deep copy situation
        if ( typeof target === "boolean" ) {
            deep = target;
            target = arguments[1] || {};
            // skip the boolean and the target
            i = 2;
        }
    
        // 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 ( 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;
                    }
    
                    // 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;
    };
    jQuery - V1.8.2 extend

     比较两个版本的jQuery,extend函数总体构架上基本没有变化,高版本中写代码更加规范了,很多var变量都前置(这是比较好的编码习惯,当然,也是为了方便压缩工具对代码进行压缩)。

    jQuery.fn.extend就是把extend函数绑定到他的原型链中。这样一来,既可以作为静态函数在$上直接引用($.extend),也可以在$(obj)上使用extend。

    注意,如果函数没有在原型链上绑定,是不能被“继承”的!

    代码大概的意思就是:

      第一个参数是boolean类型 ---------> 深度递归复制
                   |
                   |
                   ---------> 如果只有一个参数(除第一个boolean)---------> 将函数的this环境extend进去
                                           |
                                           |
                                           ---------> 将后面的参数extend到“第一个”参数中 ---------> 返回“第一个”参数

    三、问题解释

    •  第一个问题中,
    $.extend.apply( null, [ true, { "a" : 1, "b" : 2 } ] );

    extend作为一个静态函数被调用,null被绑定,但是因为满足“只有一个”参数(boolean除外)的条件 , 将函数的this环境(window)extend进去,return的对象就是window对象,所以得到的结果是

    window <- { "a" : 1, "b" : 2 }

    即,window.a = 1

     

    • 第二个问题中,
    $.extend.apply( null, [ true, { "a" : 1, "b" : 2 } ].concat( { "c" : 3, "d" : 4 } ) );

    相当于传入三个参数,第一个是true,第二个是 匿名对象{ "a" : 1, "b" : 2 },第三个是匿名对象{ "c" : 3, "d" : 4 }, 此时的this环境是null(因为将函数绑定到null上面了)。

    那么结果就是{ "a" : 1, "b" : 2, "c" : 3, "d" : 4 }, 此刻并不能在window中索引到a这个属性

    如要想要访问,那便是null.a,但这种访问方式肯定是不对的。

    由于没有变量来接收这个返回的值,所以被作为垃圾给回收了。

    有兴趣的童鞋可以试试这个:

    $.extend.apply( $, [ true, { "a" : 1, "b" : 2 } ] );
    $.extend.apply( $, [ true, { "a" : 1, "b" : 2 } ].concat( { "c" : 3, "d" : 4 } ) );

    把$作为当前的环境,看看a被绑定在那个元素上了~

     四、小结

      jQuery是一个非常优秀的JS库,也是前辈们学习JS后经验的总结和思想的结晶,从jQuery1.2版本到现在的2.0版本,代码风格上、函数处理方式上有比较明显的改变,很值得花些功夫去研究。学习的过程中多看看ta们的编码风格、编码规范,了解库的整体构架和实现原理,这样应该会有比较大的提升~

      我觉得前端这方面想独树一帜,就必须在代码中体现自己的思想。

  • 相关阅读:
    树状数组求区间最大值
    ABP Zero最新版源码
    abp zero mysql版正式发布
    基于ABP的Easyui admin framework正式开放源代码
    【推荐】ImageProcessor.Web,再也不用自己生成缩略图了
    ABP教程(四)- 开始一个简单的任务管理系统
    Abp Framework中文文档上线
    【开源】基于EF6+MVC5+API2+Easyui1.4.5+Easyui管理模板开发的管理系统
    web+ admin template,spa管理应用后台,easyui后台正式发布
    ABP教程(三)- 开始一个简单的任务管理系统 – 后端编码
  • 原文地址:https://www.cnblogs.com/hustskyking/p/extend-in-jQuery.html
Copyright © 2011-2022 走看看