为什么jQuery Extend无法递归复制这两个对象文字?

时间:2013-11-20 16:44:25

标签: javascript jquery web extend

我正在使用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);

问题:为什么没有添加“来源”选项?

3 个答案:

答案 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中的合并方法。检查这个答案:

https://stackoverflow.com/a/32141113/976556