Brad Kent Brad Kent - 4 months ago 12
Javascript Question

javascript module pattern return object reference?

my understanding is that objects are passed around by reference..
I've implemented the module patters as below.

var myModule = (function(){
var obj = {};

return {
obj: obj,
updateObj: function(newObj) {
obj = newObj;
}
}

}())

myModule.obj; // {}
myModule.updateObj({foo:'bar'});
myModule.obj; // still {} :(


Where am I going wrong? Isn't myModule.obj a reference to the internal obj var?

EDIT: ended up going with this:

var myModule = (function(){

var public = {
obj: {},
updateObj: function(newObj) {
public.obj = newObj;
}
}

return public;

}())

Answer

Where am I going wrong?

You're assigning a new reference to the obj variable, but that's not what your console code is looking at. It's looking at the reference in the obj property on the object you're returning.

Isn't myModule.obj a reference to the internal obj var?

No. This:

return {
    obj: obj
    // ...
}

copies the object reference from the variable to the property, after which there is no link between the variable and the property.

After you've created myModule, before your callto updateObj, here's what you have in memory (with some irrelevant details omitted):

 +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
 |  +−−−−−−−−−−−−−−−−−−−+                                     |
 +−>| execution context |                                     |
    +−−−−−−−−−−−−−−−−−−−+                                     |
    | obj: Ref11235     |−−−−−+                               |
    +−−−−−−−−−−−−−−−−−−−+     |                               |
                              |   +−−−−−−−−+                  |
    +−−−−−−−−−−−−−−−−−−−−−+   +−−>| object |                  |
    | variable "myModule" |   |   +−−−−−−−−+                  |
    +−−−−−−−−−−−−−−−−−−−−−+   |                               |
    | obj: Ref11235       |−−−+   +−−−−−−−−−−−−−−−−−−−−−−−+   |
    | updateObj: Ref88452 |−−−−−−>|  function             |   |
    +−−−−−−−−−−−−−−−−−−−−−+       +−−−−−−−−−−−−−−−−−−−−−−−+   |
                                  | environment: Ref71423 |−−−+
                                  | [[code]               |
                                  +−−−−−−−−−−−−−−−−−−−−−−−+

Ref11235 is just a plaeholder for the value of the object reference to that object. (Similarly Ref88452 is the object reference for the function, and Ref71423 is the object reference to the behind-the-scenes "EnvironmentRecord" object the updateObj function has a reference to so it can update that environment's obj variable.)

After your call to updateObj, you've changed the reference in the obj property of myModule, but that doesn't change the reference in the obj variable:

 +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
 |                                +−−−−−−−−+                  |
 |  +−−−−−−−−−−−−−−−−−−−+     +−−>| object |                  |
 +−>| execution context |     |   +−−−−−−−−+                  |
    +−−−−−−−−−−−−−−−−−−−+     |                               |
    | obj: Ref11235     |−−−−−+   +−−−−−−−−−−−−+              |
    +−−−−−−−−−−−−−−−−−−−+         |   object   |              |
                              +−−>+−−−−−−−−−−−−+              |
    +−−−−−−−−−−−−−−−−−−−−−+   |   | foo: "bar" |              |
    | variable "myModule" |   |   +−−−−−−−−−−−−+              |
    +−−−−−−−−−−−−−−−−−−−−−+   |                               |
    | obj: Ref65243       |−−−+   +−−−−−−−−−−−−−−−−−−−−−−−+   |
    | updateObj: Ref88452 |−−−−−−>|  function             |   |
    +−−−−−−−−−−−−−−−−−−−−−+       +−−−−−−−−−−−−−−−−−−−−−−−+   |
                                  | environment: Ref71123 |−−−+
                                  | [[code]               |
                                  +−−−−−−−−−−−−−−−−−−−−−−−+

The only change is in myModule.obj's value, which now refers to a new object.


If you change updateObj to update the property instead:

updateObj: function(newObj) {
    this.obj = newObj;
}

...then you'll see the result you expect. (At which point it would probably make sense to do away with the obj variable entirely.)