deep merge objects with AngularJS

前端 未结 5 1076
情书的邮戳
情书的邮戳 2020-11-30 07:38

Normally to shallow copy objects I would use angular.extend()

Here\'s an example of that:

var object1 = {
  \"key\": \"abc123def456\",
          


        
相关标签:
5条回答
  • 2020-11-30 07:40

    angular.merge polyfill for angular < 1.4.0

    if (!angular.merge) {
      angular.merge = (function mergePollyfill() {
        function setHashKey(obj, h) {
          if (h) {
            obj.$$hashKey = h;
          } else {
            delete obj.$$hashKey;
          }
        }
    
        function baseExtend(dst, objs, deep) {
          var h = dst.$$hashKey;
    
          for (var i = 0, ii = objs.length; i < ii; ++i) {
            var obj = objs[i];
            if (!angular.isObject(obj) && !angular.isFunction(obj)) continue;
            var keys = Object.keys(obj);
            for (var j = 0, jj = keys.length; j < jj; j++) {
              var key = keys[j];
              var src = obj[key];
    
              if (deep && angular.isObject(src)) {
                if (angular.isDate(src)) {
                  dst[key] = new Date(src.valueOf());
                } else {
                  if (!angular.isObject(dst[key])) dst[key] = angular.isArray(src) ? [] : {};
                  baseExtend(dst[key], [src], true);
                }
              } else {
                dst[key] = src;
              }
            }
          }
    
          setHashKey(dst, h);
          return dst;
        }
    
        return function merge(dst) {
          return baseExtend(dst, [].slice.call(arguments, 1), true);
        }
      })();
    }
    
    0 讨论(0)
  • 2020-11-30 07:41

    Angular 1.4 or later

    Use angular.merge:

    Unlike extend(), merge() recursively descends into object properties of source objects, performing a deep copy.

    angular.merge(object1, object2); // merge object 2 into object 1
    

    Older versions of Angular:

    There is no reason a simple recursive algorithm shouldn't work :)

    Assuming they're both the result of JSON.stringify or similar:

    function merge(obj1,obj2){ // Our merge function
        var result = {}; // return result
        for(var i in obj1){      // for every property in obj1 
            if((i in obj2) && (typeof obj1[i] === "object") && (i !== null)){
                result[i] = merge(obj1[i],obj2[i]); // if it's an object, merge   
            }else{
               result[i] = obj1[i]; // add it to result
            }
        }
        for(i in obj2){ // add the remaining properties from object 2
            if(i in result){ //conflict
                continue;
            }
            result[i] = obj2[i];
        }
        return result;
    }
    

    Here is a working fiddle

    (Note, arrays are not handled here)

    0 讨论(0)
  • 2020-11-30 07:41

    If you're using < 1.4

    You can use lodash's built in _.merge() that does the same thing as angular > 1.4's version

    Saved me from writing new functions since lodash is pretty popular with angular folks already

    0 讨论(0)
  • 2020-11-30 07:50

    In the new version of Angularjs they added merge function which will perform the deep copy.

    For the older versions, I have created my custom function by copying the code of merge function from new version of Angularjs. Below is the code for the same,

    function merge(dst){
      var slice = [].slice;
      var isArray = Array.isArray;
      function baseExtend(dst, objs, deep) {
        for (var i = 0, ii = objs.length; i < ii; ++i) {
          var obj = objs[i];
          if (!angular.isObject(obj) && !angular.isFunction(obj)) continue;
          var keys = Object.keys(obj);
          for (var j = 0, jj = keys.length; j < jj; j++) {
            var key = keys[j];
            var src = obj[key];
            if (deep && angular.isObject(src)) {
              if (!angular.isObject(dst[key])) dst[key] = isArray(src) ? [] : {};
              baseExtend(dst[key], [src], true);
            } else {
              dst[key] = src;
            }
          }
        }
    
        return dst;
      }
      return baseExtend(dst, slice.call(arguments, 1), true);
    }
    

    Hope this will help someone who is wondering why angular.merge is not working in older versions.

    0 讨论(0)
  • 2020-11-30 07:58

    here is a solution that handels multiple objects merge (more than two objects):

    Here is an extendDeep function based off of the angular.extend function. If you add this to your $scope, you would then be able to call

    $scope.meta = $scope.extendDeep(ajaxResponse1.myMeta, ajaxResponse2.defaultMeta);
    

    and get the answer you are looking for.

    $scope.extendDeep = function extendDeep(dst) {
      angular.forEach(arguments, function(obj) {
        if (obj !== dst) {
          angular.forEach(obj, function(value, key) {
            if (dst[key] && dst[key].constructor && dst[key].constructor === Object) {
              extendDeep(dst[key], value);
            } else {
              dst[key] = value;
            }     
          });   
        }
      });
      return dst;
    };
    
    0 讨论(0)
提交回复
热议问题