与AngularJS深度合并对象

通常对于浅拷贝对象,我会使用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函数已经做了深度合并,我不知道?

  • 如果不是有一个本地的方式来做到这一点在JavaScriptrecursion的n级深?

Angular 1.4或更高版本

使用angular.merge

extend()不同, merge()recursion地下降到源对象的对象属性中,执行深度复制。

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

老版本的Angular:

没有理由一个简单的recursionalgorithm不应该工作:)

假设它们都是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; } 

这是一个工作小提琴

(注意,这里不处理数组)

在Angularjs的新版本中,他们添加了合并function,将执行深层复制。

对于旧版本,我通过从新版本的Angularjs复制合并函数的代码来创build自定义函数。 下面是相同的代码,

 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不工作在旧版本。

这是一个解决scheme,handels多个对象合并(超过两个对象):

这是一个基于angular.extend函数的extendDeep函数。 如果您将其添加到您的$范围,您将可以打电话

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

angular.merge polyfill为<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); } })(); } 

如果你使用<1.4

你可以使用lodash内build的_.merge() ,它和angular> 1.4的版本做同样的事情

我已经从写作新function,因为lodash已经很有angular度的人已经很受欢迎