通常对于浅拷贝对象,我会使用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级深度?
答案 0 :(得分:39)
Angular 1.4或更高版本
与
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;
}
(注意,这里不处理数组)
答案 1 :(得分: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不能在旧版本中运行的人。
答案 2 :(得分:4)
angular.merge polyfill for angular&lt; 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);
}
})();
}
答案 3 :(得分:3)
here是一个解决多个对象合并的解决方案(超过两个对象):
这是一个基于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;
};
答案 4 :(得分:1)