1

I am using closure for privacy. I dont understand why and how to change local variable from outside of closure.

I wrote a script for explain problem to you.

var MyAjax=(function(){
  //Create a local variable for privacy
  var _opts={ 
       cache:true
   }
  ,getDefaultOptions=function(){
      return _opts
  };

  //return only getDefaultOptions function
  return { 
     getDefaultOptions:getDefaultOptions
  }
})()


//I am merging new ajax options with default options.
var defaults=MyAjax.getDefaultOptions();
var reqOptions= $.extend(defaults,{cache:false});

// I am getting expected result
console.log("extended var",reqOptions) //{cache:false}

// I am getting non expected result
// I should get {cache:true} but I am getting { cache:false }
console.log("defaults",MyAjax.getDefaultOptions()) //{cache:false} 

Why this happening and how ?

Mesut Tasci
  • 2,970
  • 1
  • 30
  • 36
  • $.extend is overwriting `defaults.cache` with false, that's what extend does. – jbabey Jul 25 '12 at 12:42
  • Change of defaults variable normal.But I invoking again MyAjax.getDefaultOptions() but returning cache as false. – Mesut Tasci Jul 25 '12 at 12:50
  • 1
    "Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object." http://stackoverflow.com/questions/6605640/javascript-by-reference-vs-by-value – jbabey Jul 25 '12 at 13:03

1 Answers1

1

The $.extend() function modifies the first argument. If you don't want that, do this:

var reqOptions = $.extend({}, defaults, {cache: false});

To elaborate: you pass a reference to the object as the first argument. Even though it's a private variable of that closure, the getter function has returned a reference to it, so it's "visible" that way. The jQuery function is written in such a way that it always directly updates the object passed as the first argument. Therefore, to make sure you don't change that object, just pass in a freshly-created object as the first argument.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • closure is returning only a json object that containing only getDefaultOptions function.How to access to _opts and change it ?.How am I see contained variables of closure ? – Mesut Tasci Jul 25 '12 at 12:49
  • Your "getDefaultOptions" function returns a reference to that "_opts" object. By returning a reference to the object, it allows outside code to modify the object; that's how object references work. Outside code cannot access "_opts" by any other way than by calling the function, because it is private, but once a reference has been exposed any other code can manipulate the object just like any other object. – Pointy Jul 25 '12 at 12:57
  • Ok.If defaults variable referencing _opts, why am I not getting same results with `var1=true; var2=var1;var2=false; console.log(var2)` ? What is the defferences ?. Does it not same `var1=true; and var1=getTrue();` This is same as use & character in PHP ? – Mesut Tasci Jul 25 '12 at 13:16
  • The difference is that "_opts" references an **object**. Those other values are primitive scalar values. – Pointy Jul 25 '12 at 14:06