Modifying jQuery extend to push array items within objects but extend other objects

后端 未结 4 917
太阳男子
太阳男子 2021-01-12 10:55

I\'m thinking this must be a common problem but can\'t seem to find the solution. Using JSON config files to extend a jQuery object that contains objects and arrays.

<
相关标签:
4条回答
  • 2021-01-12 11:12

    I know this is old, but I found this post and used Steve Blacks code above but found a few bugs :

    1. Theres an extra '}' before the 'continue' in the isArray section.
    2. If the source did not have the array at all, it would throw an error, so I added this into the isArray section

      if ( !dst[p] ) {
          dst[p] = src[p];
          continue;
      }
      

    So the finished code looks like this :

    function isDOMNode(v) {
        if ( v===null ) return false;
        if ( typeof v!=='object' ) return false;
        if ( !('nodeName' in v) ) return false; 
        var nn = v.nodeName;
        try {
          v.nodeName = 'is readonly?';
        } catch (e) {
          return true;
        }
        if ( v.nodeName===nn ) return true;
        v.nodeName = nn;
        return false;
    }
    
    function mergeRecursive() {
        // _mergeRecursive does the actual job with two arguments.
        var _mergeRecursive = function (dst, src) {
            if ( isDOMNode(src) || typeof src!=='object' || src===null) {
                return dst; 
            }
    
            for ( var p in src ) {
                if ($.isArray(src[p])) {
                    if ( !dst[p] ) {
                        dst[p] = src[p];
                        continue;
                    }
                    $.merge(dst[p],src[p]);
                    var dupes = {}, singles = [];
                    $.each( dst[p], function(i, el) {
                        if ((dupes[el.name] > -1) &&  (el.name)) {
                            $.extend(singles[dupes[el.name]],el);
                        } else {
                            if (el.name) {
                                dupes[el.name] = i;
                            }
                         singles.push(el);
                       }
                    });
                    dst[p] = singles;
                    continue;        
                }
    
                if ( !src.hasOwnProperty(p) ) continue;
                if ( src[p]===undefined )     continue;
                if ( typeof src[p]!=='object' || src[p]===null) {
                    dst[p] = src[p];
                } else if ( typeof dst[p]!=='object' || dst[p]===null ) {
                    dst[p] = _mergeRecursive(src[p].constructor===Array ? [] : {}, src[p]); 
                } else {              
                    _mergeRecursive(dst[p], src[p]);
                }
            }
            return dst;
        }
    
        // Loop through arguments and merge them into the first argument. 
        var out = arguments[0];
        if ( typeof out!=='object' || out===null) return out;
        for ( var i=1, il=arguments.length; i<il; i++ ) {
          _mergeRecursive(out, arguments[i]);
        }
        return out;
    }
    
    0 讨论(0)
  • 2021-01-12 11:30

    I used this solution http://jsfiddle.net/PmuwV/2/ modified from How can I merge properties of two JavaScript objects dynamically? also from JavaScript equivalent of jQuery's extend method

    requires isDOMNode() I just added in a jquery merge (yes I feel dirty too) on arrays in which duplicates will need to be cleaned up post merge. The Jquery source for extend does something very similar but i found this to be more readable.

    function mergeRecursive() {
      // _mergeRecursive does the actual job with two arguments.
      var _mergeRecursive = function (dst, src) {
        if ( isDOMNode(src) || typeof src!=='object' || src===null) {
          return dst; 
        }
    
        for ( var p in src ) {
    
    //my added bit here - [SB]
          if ($.isArray(src[p])){
              $.merge(dst[p],src[p]);
              var dupes = {},
                   singles = [];
              $.each(  dst[p], function(i, el) {
                 if ((dupes[el.name] > -1) &&  (el.name)) {
                     $.extend(singles[dupes[el.name]],el);
                 }else{
                      if (el.name ){
                         dupes[el.name] = i;
                      }
                     singles.push(el);
                 }
             });
             dst[p] = singles;
             }
             continue;        
          }
    //the rest is original - [SB]
    
          if( !src.hasOwnProperty(p) ) continue;
          if ( src[p]===undefined ) continue;
          if ( typeof src[p]!=='object' || src[p]===null) {
            dst[p] = src[p];
          } else if ( typeof dst[p]!=='object' || dst[p]===null ) {
            dst[p] = _mergeRecursive(src[p].constructor===Array ? [] : {}, src[p]); 
          } else {              
            _mergeRecursive(dst[p], src[p]);
          }
        }
        return dst;
      }
    
      // Loop through arguments and merge them into the first argument. 
      var out = arguments[0];
      if ( typeof out!=='object' || out===null) return out;
      for ( var i=1, il=arguments.length; i<il; i++ ) {
        _mergeRecursive(out, arguments[i]);
      }
      return out;
    }
    
    0 讨论(0)
  • 2021-01-12 11:30
    <html>
    <head>
    <script type="text/javascript" src="./jquery-2.1.3.js"></script> <!-- for json extend / merge -->
    <script type="text/javascript" src="./jQuery.extendext.min.js"></script> <!-- for json extend / merge - with array extend (instead of array overwrite) - https://github.com/mistic100/jQuery.extendext -->
    
    <script>
    var jsonResult = {};
    var json1 =
    {
        "properties":
        {
            "street_address": { "type": "string" },
            "city": { "type": "string" },
            "state": { "type": "string" }
        },
        "required": ["street_address", "city", "state"]
    };
    var json2 =
    {
        "properties":
        {
            "country": { "type": "string" },
            "country-dial-code": { "type": "integer" },
            "country-short": { "type": "string" }
        },
        "required": ["country", "country-dial-code", "country-short"]
    };
    $.extendext(true, 'extend', jsonResult, json1, json2);
    console.log(JSON.stringify(jsonResult));
    /* output ->
    {   "properties":
        {   "street_address":{"type":"string"},
            "city":{"type":"string"},
            "state":{"type":"string"},
            "country":{"type":"string"},
            "country-dial-code":{"type":"integer"},
            "country-short":{"type":"string"}
        },
        "required":["street_address","city","state","country","country-dial-code","country-short"]
    }
    */
    </script>
    </head>
    <body>
    </body>
    </html>
    
    0 讨论(0)
  • 2021-01-12 11:33

    It's quite straightforward with lodash library

    var targetObj = {
        customerId: "123", 
        orders: [
            "item1", "item2"
        ]
    };
    
    var otherObj = {
        customerName: "John", 
        orders: [
            "item3", "item4"
        ]
    };
    
    _.merge(targetObj, otherObj, function (a, b) {
      if (_.isArray(a)) {
        return a.concat(b);
      }
    });
    

    Result is:

    targetObj = {
        customerId: "123",
        customerName: "John",
        orders: [
            "item1", "item2", "item3", "item4"
        ]       
    }
    
    0 讨论(0)
提交回复
热议问题