我正在使用jQuery $ .extend方法对两个对象进行递归合并,但它没有像我期望的那样工作。 (旁白:这些对象文字采用CKEditor配置其工具栏所需的格式。)
预期结果:最大化,显示块和来源。
实际结果:最大化,ShowBlocks。
var obj1 = [
{ name: 'styles', items: ['Format', 'Font', 'FontSize'] },
{ name: 'colors', items: ['TextColor', 'BGColor'] },
{ name: 'tools', items: ['Maximize', 'ShowBlocks'] },
];
var obj2 = [
{ name: 'tools', items: ['Source'] }
];
var recursiveFail = $.extend(true, {}, obj1, obj2);
// Test result here....
alert(recursiveFail[2].items);
问题:为什么没有添加“来源”选项?
答案 0 :(得分:2)
$.extend
不能那样工作:它会将对象的属性从一个对象复制到另一个对象。它无法识别“我看到'name'在这个数组的这些对象中是相同的,所以我知道合并'items'数组。”
您可能需要编写自己的循环,以obj1
来扩充obj2
。
// Add 'Source' command to the tools group
for (var i = 0; i < obj1.length; i++) {
if (obj1[i].name === 'tools') {
obj1[i].items.push('Source');
break;
}
}
答案 1 :(得分:1)
$.extend
并不意味着以这种方式使用。
但是,您可以编写自己的扩展/合并功能。下面是一个函数示例,它将从多个提供的数组中合并的每个对象(基于特定键的值)合并在一起。
以下合并算法将覆盖原始值并将连接数组。 初始数组及其对象不会被修改。
如果你只需要这样做一次就可能有点过头了,但是这是你如何实现你自己的封装合并算法的一个例子。
function mergeOnKey(mergeKey) {
var mergedObjectsIndex = {},
mergedObjects = [],
arrays = Array.prototype.slice.call(arguments, 1),
i = 0,
arraysLen = arrays.length,
x, arrLen, arr, obj, k,
mergeVal, mergedObjIndex,
mergedObj, mergedVal;
for (; i < arraysLen ; i++) {
arr = arrays[i];
for (x = 0, arrLen = arr.length; x < arrLen; x++) {
obj = arr[x];
mergeVal = obj[mergeKey];
mergedObjIndex = mergedObjectsIndex[mergeVal];
if (typeof mergedObjIndex === 'undefined') {
mergedObjectsIndex[mergeVal] = mergedObjects.push($.extend({}, obj)) - 1;
continue;
}
mergedObj = mergedObjects[mergedObjIndex];
for (k in obj) {
if (!obj.hasOwnProperty(k) || k === mergeKey) continue;
if (Array.isArray(mergedVal = mergedObj[k])) mergedObj[k] = mergedVal.concat(obj[k]);
else mergedObj[k] = obj[k];
}
}
}
return mergedObjects;
}
然后您就可以使用它:
var obj1 = [
{ name: 'styles', items: ['Format', 'Font', 'FontSize'] },
{ name: 'colors', items: ['TextColor', 'BGColor'] },
{ name: 'tools', items: ['Maximize', 'ShowBlocks'] }
];
var obj2 = [
{ name: 'tools', items: ['Source'], test: 'test' }
];
var merged = mergeOnKey('name', obj1, obj2);
console.log(merged[2].items); //["Maximize", "ShowBlocks", "Source"]
答案 2 :(得分:0)
您可以使用lodash library中的合并方法。检查这个答案: