2

I have observed an odd issue in jQuery's $.extend method and referencing an array (which is considered an Object in JavaScript).

I use a defaults object, defined as follows:

var defaults = {
    numbers: []
};

I have a config option I then pass a function, defined as follows:

var config = {
    numbers: [1, 2, 3]
};

Within a function, I extend these two (using a deep $.extend):

function configure(settings) {
    var nums = $.extend(true, {}, defaults, settings);

    nums.numbers.push(4);

    console.log(settings, nums);
}

configure(config);

When I log these two, the results are as follows:

settings: {"numbers":[1,2,3]}
nums: {"numbers":[1,2,3,4]}

What I am failing to understand is, jQuery merges the objects from left to right.

I would expect that since settings is the last object that is extended, the numbers array that's created in nums is a reference to settings.numbers (since settings is the last object to be $.extended). This is not the case (as you can see when I log the final results).

Can somebody please explain why? It was the cause of a difficult to find bug in my app so want to ensure I understand it so it does not happen again.

keldar
  • 6,152
  • 10
  • 52
  • 82
  • 1
    This is exactly what a deep copy means -- it will copy all the contents of the `numbers` array into a new array. Do a shallow copy if you want to only copy the reference to the array object. Related question: http://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow-copy – blgt Jun 04 '15 at 13:13

1 Answers1

2

You made a deep merge:

On a deep extend, Object and Array are extended

The target object is the first object after your deep boolean.

In your case, it's {} and also nums because of your assignation.

settings isn't the target object. Its numbers array is therefore not the one of nums.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758