Search code examples
javascriptjquerywebextend

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


I am using jQuery $.extend method to do a recursive merge of two objects, but it is not working as I would expect. (Aside: these object literals are in the format required by CKEditor to configure its toolbar.)

Expected Result: Maximize, ShowBlocks, and Source.

Actual Result: Maximize, 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);

Question: Why isn't the 'Source' option being added in?


Solution

  • $.extend doesn't work like that: it will copy properties of objects from one object to another. It isn't able to identify things like "I see that 'name' is the same in these objects of this array, so I know to merge the 'items' arrays."

    You'll probably have to write your own loop to augment obj1 with 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;
        }
    }