簡體   English   中英

為什么jQuery Extend無法遞歸地復制這兩個對象文字?

[英]Why does jQuery Extend fail to recursively copy these two object literals?

我正在使用jQuery $ .extend方法對兩個對象進行遞歸合並,但是它沒有按我期望的那樣工作。 (此外:這些對象文字是CKEditor配置其工具欄所需的格式。)

預期結果:最大化,ShowBlocks和Source。

實際結果:最大化,顯示塊。

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

問題:為什么不添加“源”選項?

$.extend不能那樣工作:它將對象的屬性從一個對象復制到另一個對象。 它無法識別“我看到此數組的這些對象中的'name'是相同的,所以我知道要合並'items'數組”這樣的事情。

您可能必須編寫自己的循環才能用obj2擴展obj1

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

$.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"]

您可以使用lodash庫中的 merge方法。 檢查以下答案:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM