Why $.extend(someObj, anotherObj) might be dangerous!
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!