• js引用类型赋值,深拷贝与浅拷贝


      JS中引用类型使用等号“=” 赋值,相当于把原来对象的地址拷贝一份给新的对象,这样原来旧的对象与新的对象就指向同一个地址,改变其中一个对象就会影响另外那个对象,也就是所谓的浅拷贝。例如:

    var arr = ["One","Two","Three"];
    
    var arrto = arr;
    arrto[1] = "test";
    document.writeln("数组的原始值:" + arr + "<br />");//Export:数组的原始值:One,test,Three
    document.writeln("数组的新值:" + arrto + "<br />");//Export:数组的新值:One,test,Three

      其实很多时候这并不是我们想要的结果,修改新对象时我们希望不要影响原来的对象。

      今天我想说的是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;
    };

      $.extend(target,object1,objectN); 合并object1与objectN至target中,此操作会改变target的结构。

      若不想改变原来对象,可以设置第一个参数为一个空对象{}: $.extend({},object1,objectN);

      $.extend()第一个参数也可以为布尔类型,只是是否是深拷贝。$.extend(true,target,object1,objectN);设为true则表示深拷贝,不设默认为浅拷贝,此处只能设true,不能设false。

      The merge performed by $.extend() is not recursive by default; if a property of the first object is itself an object or array, it will be completely overwritten by a property with the same key in the second or subsequent object. The values are not merged. This can be seen in the example below by examining the value of banana. However, by passing true for the first function argument, objects will be recursively merged.

    Warning: Passing false for the first argument is not supported.

      Undefined properties are not copied. However, properties inherited from the object's prototype will be copied over. Properties that are an object constructed via new MyCustomObject(args), or built-in JavaScript types such as Date or RegExp, are not re-constructed and will appear as plain Objects in the resulting object or array.

    On a deep extend, Object and Array are extended, but object wrappers on primitive types such as String, Boolean, and Number are not. Deep-extending a cyclical data structure will result in an error.

    For needs that fall outside of this behavior, write a custom extend method instead, or use a library like lodash.

    Examples:

    Example: Merge two objects, modifying the first.

     1 <!doctype html>
     2 <html lang="en">
     3 <head>
     4   <meta charset="utf-8">
     5   <title>jQuery.extend demo</title>
     6   <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
     7 </head>
     8 <body>
     9  
    10 <div id="log"></div>
    11  
    12 <script>
    13 var object1 = {
    14   apple: 0,
    15   banana: { weight: 52, price: 100 },
    16   cherry: 97
    17 };
    18 var object2 = {
    19   banana: { price: 200 },
    20   durian: 100
    21 };
    22  
    23 // Merge object2 into object1
    24 $.extend( object1, object2 );
    25  
    26 // Assuming JSON.stringify - not available in IE<8
    27 $( "#log" ).append( JSON.stringify( object1 ) );
    28 </script>
    29  
    30 </body>
    31 </html>

    输出为:{"apple":0,"banana":{"price":200},"cherry":97,"durian":100}

    object1.banana.price = 300; //改变object1中的banana对象的price属性为300
    $( "#log" ).append( JSON.stringify( object1 ) ); //输出为 {"banana":{"price":300},"durian":100},object1的改变会影响object2

    Example: Merge two objects recursively, modifying the first.

    <!doctype html>
    <html lang="en">
    <head>
      <meta charset="utf-8">
      <title>jQuery.extend demo</title>
      <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
    </head>
    <body>
     
    <div id="log"></div>
     
    <script>
    var object1 = {
      apple: 0,
      banana: { weight: 52, price: 100 },
      cherry: 97
    };
    var object2 = {
      banana: { price: 200 },
      durian: 100
    };
     
    // Merge object2 into object1, recursively
    $.extend( true, object1, object2 );
     
    // Assuming JSON.stringify - not available in IE<8
    $( "#log" ).append( JSON.stringify( object1 ) );
    </script>
     
    </body>
    </html>

    输出为:{"apple":0,"banana":{"weight":52,"price":200},"cherry":97,"durian":100}

     object1.banana.price = 300; //改变object1中的banana对象的price属性为300

       $( "#log" ).append( JSON.stringify( object1 ) ); //输出为 {"banana":{"price":200},"durian":100},object1的改变不会影响object2

    Example: Merge defaults and options, without modifying the defaults. This is a common plugin development pattern.

     1 <!doctype html>
     2 <html lang="en">
     3 <head>
     4   <meta charset="utf-8">
     5   <title>jQuery.extend demo</title>
     6   <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
     7 </head>
     8 <body>
     9  
    10 <div id="log"></div>
    11  
    12 <script>
    13 var defaults = { validate: false, limit: 5, name: "foo" };
    14 var options = { validate: true, name: "bar" };
    15  
    16 // Merge defaults and options, without modifying defaults
    17 var settings = $.extend( {}, defaults, options );
    18  
    19 // Assuming JSON.stringify - not available in IE<8
    20 $( "#log" ).append( "<div><b>defaults -- </b>" + JSON.stringify( defaults ) + "</div>" );
    21 $( "#log" ).append( "<div><b>options -- </b>" + JSON.stringify( options ) + "</div>" );
    22 $( "#log" ).append( "<div><b>settings -- </b>" + JSON.stringify( settings ) + "</div>" );
    23 </script>
    24  
    25 </body>
    26 </html>

    输出为:

    defaults -- {"validate":false,"limit":5,"name":"foo"}
    options -- {"validate":true,"name":"bar"}
    settings -- {"validate":true,"limit":5,"name":"bar"}

    参考资料:jQuery.extend的实现方式

  • 相关阅读:
    转 IDEA 解决代码提示功能消失
    模态框居中显示
    DetachedCriteria和Criteria的使用方法
    struts2配置文件详解
    springMVC上传图片
    在linux下运行mongodb
    webSocket客服在线交谈
    接口自动化
    easyui input文本框清除值
    Spring总结
  • 原文地址:https://www.cnblogs.com/zhangcybb/p/4664711.html
Copyright © 2020-2023  润新知