Juri Strumpflohner mainly operates in the web sector developing rich applications with HTML5 and JavaScript. Beside having a Java background and developing Android applications he currently works as a software architect mainly dealing with the .Net technology stack. When he’s not coding or blogging about his newest discoveries he is practicing Yoseikan Budo where he owns a 2nd DAN. Juri is a DZone MVB and is not an employee of DZone and has posted 34 posts at DZone. You can read more from them at their website. View Full User Profile

Why $.extend(someObj, anotherObj) Might be Dangerous!

07.28.2012
| 816 views |
  • submit to reddit

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 have dangerouse side effects if not used properly!

Suppose you have an object, obj1 defines 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!

Published at DZone with permission of Juri Strumpflohner, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)