zoukankan      html  css  js  c++  java
  • jquery源码解析:jQuery扩展方法extend的详解

    jQuery中要扩展方法或者属性都是通过extend方法实现的。所谓的jQuery插件也是通过extend方法实现的。

    jQuery.extend扩展的是工具方法,也就是静态方法。jQuery.fn.extend扩展的是实例方法。

    当只传入一个对象的时候,里面的方法和属性是扩展到this上的。比如:

    $.extend(  {  aaa:function(){}, bbb:function(){}  }  ) ,这里的this是$,所以用这种形式$.aaa()调用。

    $.fn.extend(  {  aaa:function(){}, bbb:function(){}  }  ) ,这里的this是$.fn(原型),所以用这种形式$("").aaa()调用。      

    当传入多个对象的时候,后面的对象都是扩展到第一个对象身上。比如:

    var a ={};

    $.extend(  a, {name:"hello"}, {age:30}  ),这时a = {name:"hello",age:30}

    还可以做深拷贝和浅拷贝(拷贝继承)。比如:

    var a = {};var b = {  name:{age:30}  };

    $.extend( a , b );   a.name.age = 20,这时你打印b.name.age,你会发现也是20.这就是浅拷贝。没有对对象进行复制,只对简单字符做了复制(如果name是字符串,那么改变a.name的值,即便是浅拷贝也不会影响b.name的值)。但是你可以使用深拷贝:

    $.extend( true , a , b );     a.name.age = 20,这时你打印b.name.age,你会发现是30,没有改变。因为深拷贝,无论b的属性是什么,都会重新复制一份。

    jQuery.extend = jQuery.fn.extend = function() {  

      var options, name, src, copy, copyIsArray, clone,
        target = arguments[0] || {},
        i = 1,
        length = arguments.length,
        deep = false;     //默认为浅拷贝

        if ( typeof target === "boolean" ) {     //看第一个参数是否是boolean
          deep = target;     //如果是,就证明目标对象是第二个参数,第一个参数是来判断是不是深拷贝的
          target = arguments[1] || {};
          i = 2;
        }

        if ( typeof target !== "object" && !jQuery.isFunction(target) ) { //必须 为对象或者函数
          target = {};
        }

        if ( length === i ) {   //如果只有一个对象的时候,目标对象指向this,往this上扩展方法和属性
          target = this;
          --i;
        }

        for ( ; i < length; i++ ) {
          if ( (options = arguments[ i ]) != null ) {    //判断扩展的对象不是null
            for ( name in options ) {     //取对象中的属性名
              src = target[ name ];     //取目标对象的name属性值
              copy = options[ name ];   //取扩展对象的name属性值

              if ( target === copy ) {    

                 //解决循环引用的问题,比如:var a ={};$.extend( a , { name:a } ),如果不做这个处理,将会得到一个死循环的对象(a{name:{name:{name:{...}}}}),加了这个,就扩展不上,a还是{}
                continue;
              }

              if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {

              //如果是深拷贝,并且扩展对象的name属性值存在,并且扩展对象是一个对象自变量(或者是一个数组),就进入if语句

              
                if ( copyIsArray ) {    //如果扩展对象的name属性值是数组,进入if语句
                  copyIsArray = false;
                  clone = src && jQuery.isArray(src) ? src : [];

                  //如果目标对象的name属性值是一个数组,就取这个数组,如果不是,就取[]

                } else {   //如果扩展对象的name属性值是对象自变量
                  clone = src && jQuery.isPlainObject(src) ? src : {};

                  //如果目标对象的name属性值是一个对象自变量,就取这个对象自变量,如果不是,就取{}
                }

                target[ name ] = jQuery.extend( deep, clone, copy );

                //递归调用extend,深拷贝扩展对象的name属性值(对象或者数组)到clone。

                //递归结束后,返回clone,赋值给目标元素的name属性

                //这就把扩展对象的所有属性都扩展到目标对象中了。

              } else if ( copy !== undefined ) {   
                target[ name ] = copy;
              }
            }
          }
        }

        return target;

    }

    jQuery中使用的是拷贝继承。

    加油!

  • 相关阅读:
    SET ROWCOUNT,SET NOCOUNT
    JS是按值传递还是按引用传递?
    Debug目录、Release目录,bin目录、obj目录,vshost.exe.config文件、.exe.config文件分析【C#】
    写window应用程序日志System.Diagnostics.EventLog.WriteEntry
    X-UA-Compatible设置兼容模式
    Linq的Distinct方法的扩展
    SQL Server 系统表简介
    sql server 常用的系统存储过程
    C# Timer用法及实例详解
    ASP.NET MVC内置的Filter实现介绍
  • 原文地址:https://www.cnblogs.com/chaojidan/p/4145168.html
Copyright © 2011-2022 走看看