首页 > 技术文章 > jquery源码笔记(四): jquery.extend=jquery.fn.extend

a-lonely-wolf 2016-07-25 00:25 原文

extend()  方法,   合并两个或更多对象的属性到第一个对象中,jQuery后续的大部分功能都通过该函数扩展,

当参数只有一个对象时,则将对象的属性添加到jQuery对象中。

jquery 中扩展插件的形式:  2种方法

$.extend({                //扩展工具方法
        aaa:function(){
            alert(10);
        },
        bbb:function(){
            alert(20)
        }
    });

    $.fn.extend({            //扩展jquery实例方法
        aaa:function(){
            alert("fn  1");
        },
        bbb:function(){
            alert("fn  2");
        }
    });

    $.extend() ; this  -> $   this.aaa  ->  $.aaa();
    $.fn.extend();   this -> $.fn (原型)  this.aaa  -> $().aaa()

当参数中有多个对象的时候,后面的对象都是扩展到第一个对象上:

    var a = {name:"Linda"};
    $.extend(a,{name:"Joke",age:20},{address:"China"});
    console.log(a);        //    { name="Joke",  age=20,  address="China"}

还有  深拷贝 和 浅拷贝  , jquery默认是浅拷贝  

浅拷贝:
var a = {name:"Linda"};
    var b = {firends:['aa','bb','cc']};
    $.extend(a,b);
    a.firends.push('dd');
    console.log(b);        //    { firends:['aa','bb','cc','dd']}

深拷贝:
var a = {name:"Linda"};
    var b = {firends:['aa','bb','cc']};
    $.extend(true,a,b);  //第一个参数设置为 true , 那就是 深拷贝
    a.firends.push('dd');  此时a 的引用类型的 修改对  b 没有影响
    console.log(b);        //    { firends:['aa','bb','cc']}

源码的 分解:

 jQuery.extend = jQuery.fn.extend = function() {
    定义一些变量
  if(){} 看看是不是深拷贝情况
  if(){}  看看参数正确不
  if(){} 看看是不是插件情况      for(){ 可能有多个对象情况
      if(){} 防止循环引用
      if(){} 深拷贝
       else if(){} 浅拷贝
   }

 源码:

    jQuery.extend = jQuery.fn.extend = function() {
    var options, name, src, copy, copyIsArray, clone,
        target = arguments[0] || {},                    //target存储第一个参数,
        i = 1,
        length = arguments.length,
        deep = false;
    // Handle a deep copy situation
    if ( typeof target === "boolean" ) {            //当第一个参数是boolean类型时,知道是深拷贝还是浅拷贝,默认是false  浅拷贝
        deep = target;
        target = arguments[1] || {};                // 此时 target就存储第一个对象
        // 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表示target 存储的对象在参数中的位置, 如果等于 参数的长度,说明 是向jquery中 添加属性
        --i;                    //也就是只有一个参数,或者2个参数,但第一个参数是boolean类型,实际也就是1个
    }
    for ( ; i < length; i++ ) {
        // Only deal with non-null/undefined values
        if ( (options = arguments[ i ]) != null ) {        //如果传入的参数,不是null
            // Extend the base object
            for ( name in options ) {                //对对象进行for循环
                src = target[ name ];            //对象扩展的目标,
                copy = options[ name ];
                // Prevent never-ending loop
                if ( target === copy ) {        //防止是循环引用,例如:  var a = {}; b={name:a};  b中的name属性的值是一个引用类型a ,
                    continue;                            // 如果没有这个判断,那么 $.extend(a,b); 后 a就是一个无线循环的引用,            
                }
                // Recurse if we're merging plain objects or arrays
                if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
                    //dep是true,copy也存在,copy是json格式,或者 copy是一个数组
                    if ( copyIsArray ) {    //如果copy是一个数组,
                        copyIsArray = false;
                        clone = src && jQuery.isArray(src) ? src : [];    //判断第一个对象的属性值,是不是数组;
                    } else {
                        clone = src && jQuery.isPlainObject(src) ? src : {};    //判断第一个对象的属性值,是不是json;
                    }
                    // 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 中 :  拷贝继承,能够 满足  构造函数继承和 原型继承 方式,

js中 :  构造函数继承 //原型继承

推荐阅读