37

通常、私が使用する浅いコピーオブジェクトにangular.extend()

その例を次に示します。

var object1 = {
  "key": "abc123def456",
  "message": {
    "subject": "Has a Question",
    "from": "example1@example.com",
    "to": "example2@example.com"
   }
};

var object2 = {
  "key": "00700916391"
};

console.log(angular.extend({}, object1, object2));

私たちに与えるでしょう:

{
 "key": "00700916391",
 "message": {
   "subject": "Has a Question",
   "from": "example1@example.com",
   "to": "example2@example.com"
  }
}

しかし、親キーが子オブジェクトによって上書きされないように、オブジェクトをマージしたい場合はどうすればよいでしょうか。

var object1 = {
  "key": "abc123def456",
  "message": {
    "subject": "Has a Question",
    "from": "example1@example.com",
    "to": "example2@example.com"
   }
};

var object2 = {
  "key": "00700916391",              //Overwrite me
  "message": {                       //Dont overwrite me!
    "subject": "Hey what's up?",     //Overwrite me
    "something": "something new"     //Add me
   }
};

console.log(merge(object1, object2));

私たちに与えるでしょう:

{
 "key": "00700916391",
 "message": {
   "subject": "Hey what's up?",
   "from": "example1@example.com",
   "to": "example2@example.com",
   "something": "something new"
  }
}
  • 私が気付いていないディープ マージを既に実行している Angular 関数はありますか?

  • そうでない場合、JavaScriptでnレベルの深さで再帰的にこれを行うネイティブな方法はありますか?

4

5 に答える 5

39

Angular 1.4 以降

使用angular.merge:

とは異なりextend()merge()ソース オブジェクトのオブジェクト プロパティに再帰的に下降し、ディープ コピーを実行します。

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

古いバージョンの Angular:

単純な再帰アルゴリズムが機能しない理由はありません:)

どちらも JSON.stringify などの結果であると仮定します。

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;
}

これが実用的なフィドルです

(注、配列はここでは扱われません)

于 2013-06-21T19:37:38.463 に答える
6

Angularjs の新しいバージョンでは、ディープ コピーを実行するマージ機能が追加されました。

古いバージョンの場合、新しいバージョンの Angularjs からマージ関数のコードをコピーしてカスタム関数を作成しました。以下は同じコードです。

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);
}

古いバージョンで angular.merge が機能しない理由を疑問に思っている人に、これが役立つことを願っています。

于 2015-03-12T06:46:43.103 に答える
4

angular < 1.4.0 の angular.merge ポリフィル

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);
    }
  })();
}
于 2015-06-24T14:27:45.937 に答える
3

複数のオブジェクトのマージ (2 つ以上のオブジェクト) を処理するソリューションを次に示します

これは angular.extend 関数に基づいた extendDeep 関数です。これを $scope に追加すると、呼び出すことができます

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

探している答えを得ることができます。

$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;
};
于 2014-08-11T14:20:24.413 に答える
1

1.4未満を使用している場合

angular> 1.4のバージョンと同じことを行うlodash組み込みの_.merge()を使用できます

lodashすでに角度のある人々にかなり人気があるため、新しい関数を作成する必要がなくなりました

于 2015-06-25T14:31:17.220 に答える