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.

1
  • 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: stackoverflow.com/questions/184710/… Commented Jun 4, 2015 at 13:13

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Understood and thanks! Is there a trick to reassign the nums.numbers reference back to settings.numbers?
@keldar In your case it looks like you could simply do a non deep merge: var nums = $.extend({}, defaults, settings);
Unfortunately my full config is a little more complex than the code shown here so a non-deep merge isn't an option in this instance.
The just set the reference manually, if you need a special behavior

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.