Juri Strumpflohner
Juri Strumpflohner Juri is a full stack developer and tech lead with a special passion for the web and frontend development. He creates online videos for Egghead.io, writes articles on his blog and for tech magazines, speaks at conferences and holds training workshops.

Why $.extend(someObj, anotherObj) might be dangerous!

2 min read

You often have the need to merge two objects. A common use case is that of combining parameters for a $.ajax call. jQuery has a nice function for that, namely jQuery.extend. The function definition is something like jQuery.extend(target, [object 1], [object 2]). But attention, this might lead to dangerous side effects if not used properly!

Suppose you have an object, obj1 defined like

var obj1 = { 
    value: 1
};

And you need to execute a request to your backend server with some additional parameters, including the values of obj1. Your code might look like

var sendToServer = function(params, successCb, errorCb){
return $.ajax({
url: "/api/someurl",
type: "GET",
dataType: "json",
data: params,
success: successCb,
errorCb: errorCb
});
}

...
sendToServer(
$.extend(obj1, { value: 2, someOtherParam: "hello" }),
function(resultData) {
console.log("The value of obj1: " + obj1.value);
},
function(e) {
console.log("An error happened");
});

On line 14 I’m basically giving the parameters to the sendToServer(..) function by combining those in obj1 with some new ones. This is possible since the $.extend(…) function directly returns the result of the combination of the passed objects.

Can you guess the output of line 16?

> The value of obj1: 2
Surprised?  Well, take a look at line 14 again and then on the signature of jQuery.extend(target, [object 1], [object 2]) . What happens there is a copy of the values provided in the new object, namely { value: 2, someOtherParam: “hello” } onto obj1 , hence overwriting obj1’s property value , setting it to 2.
The correct version of line 14 would therefore probably be
$.extend({}, obj1, { value: 2, someOtherParam: “hello” })
In this version, the values of obj1 and { value: 2, someOtherParam: “hello” } are copied onto a new object {} , thus not modifying the existing instance of obj1.

Here’s a  live example that mimics the odd behavior.  Attention to this!


Questions? Thoughts? Hit me up on Twitter
comments powered by Disqus