$.extend $().extend() 深复制 和 浅复制

js 中分为基本变量,和引用变量。在$.extend(),体现得非常深刻。
除了数组,对象,其他的变量都可以称为基本变量。


var a = 3;
var b = a;
 b = 4;
console.log(a);  //3
console.log(b);  //4

var a = {name:"strong"}
var b = a;
b.name = "Lee";
console.log(a.name) //  Lee;
console.log(b.name) //Lee;

ps:可见,b属性的变化,影响到了a , 这种赋值就是浅复制,而取消这种影响,就是深复制 ;

在jQuery源码中,对于 对象 还有一个判断函数 是 $.isPlainObject(),用于判断此对象是否为“纯对象”,纯对象就是变量直接申请的对象。


var  a = {
    a:3
};

function cons(){
   this.a = 3;
}

var b = new cons();
//  a就是纯对象,而b就不是。

以下为jquery中 isPlainObject 的源码。


//此函数的核心,就是以object.prototype.constructor 属性,来判断是否为纯对象。
//当 constructor是 Object() 时,为纯对象;当为其他构造函数时就是非纯函数。

isPlainObject: function( obj ) {
        var proto, Ctor;

        // Detect obvious negatives
        // Use toString instead of jQuery.type to catch host objects
        if ( !obj || toString.call( obj ) !== "[object Object]" ) {
            return false;
        }

        proto = getProto( obj );     //obj的原型

        // Objects with no prototype (e.g., `Object.create( null )`) are plain
        if ( !proto ) {
            return true;
        }

        // Objects with prototype are plain if they were constructed by a global Object function
        Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;

        return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
    }
        

深层复制的基本原理就是将对象引用,变为基本变量赋值,这样就不会出现对象引用后,修改对象属性,造成原对象属性污染。通俗一点,就是要把对象的属性(此属性为基本变量) 赋值给 另一个对象的相应属性;

所以我们可以自己先写一个较为简单的 深层复制 对象扩展函数,


function extend(target,src){
   for( i in src){
      var a = target[i]?target[i]:{};
       //判断纯对象,并递归或直接赋值;
      target[i] = $.isPlainObject(src[i])?extend(a,src[i]):src[i]; 
   }    
   return target; 
}

ps:jquery中的深层复制只能对于纯对象,以下特例不会进行深层复制的

 function a(){
   this.a = 3;
 }

var b = {
 c :3,
 d : new a()
 }

var e = {};


$.extend(e,b);

b当中的d属性并不会深层复制给e,当e改变d属性时会影响b.d 的值;

以下为jquery中extend的源码:


jQuery.extend = jQuery.fn.extend = function() {
   //arguments[0] -> boolean;
   //arguments[1] -> target;
   //arguments[2] -> src 
    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;

        // 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
    //like $().extend({a:3})  
    //另外一种形式$.extend(a,b)  //jquery工具方法;
    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
                //recurse 递归吧
                if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
                    ( copyIsArray = jQuery.isArray( copy ) ) ) ) {    

                    if ( copyIsArray ) {    // 此if,根据src 类型 , 改变clone;
                        copyIsArray = false;
                        clone = src && jQuery.isArray( src ) ? src : [];  
                    } else {
                        clone = src && jQuery.isPlainObject( src ) ? src : {};
                    }

                    // Never move original objects, clone them
                    //copy 是对象,且好几层对象,递归复制,保障深层复制成功。
                    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;
};

你可能感兴趣的:($.extend $().extend() 深复制 和 浅复制)