0

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;

}())
5
  • I may be wrong, but from a quick look, your parentheses may be off. Shouldn't it be (function() { ... })() ? Commented Aug 4, 2016 at 15:42
  • There is a syntax error in there...somewhere Unexpected token }. Commented Aug 4, 2016 at 15:46
  • 1
    @SpencerWieczorek yes, obj = newObj, here comma should be ;. Ignoring syntax errors Commented Aug 4, 2016 at 15:46
  • thanks @Tushar and SpencerWieczorek typo fixed Commented Aug 4, 2016 at 16:19
  • @duxfox-- Nope, that the immediately invoking function pattern Commented Aug 4, 2016 at 16:33

5 Answers 5

5

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.)

Sign up to request clarification or add additional context in comments.

3 Comments

Vote + 1. For those diagrams. How did you create those?
@Tushar: Text editor. There's a secret to lining up the and + though. ;-)
I'm a bit conflicted.. Awesome internals explanation and fix via using this.. @ivan-schmidt's answer wins in the succinctness category
3

The problem is that obj inside the updateObj does not refer to the obj variable that is defined inside the module. To refer to the same obj as in the myModule, use this context.

this.obj = newObj;

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

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

console.log(myModule.obj);
myModule.updateObj({
    foo: 'bar'
});
console.log(myModule.obj);

Comments

2

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

No, it isn't.

var obj = {}; creates an object and assigns a reference to it as the value of obj.

obj: obj copies the value of obj (i.e. the reference) to the obj property of the other object.

obj = newObj overwrites the value of obj with a reference to the new object. This does not touch the obj property so it is still a reference to the first object.

1 Comment

That's what I thought may be going on... obj = newObj is overwriting/replacing
1

This one is similar to code below:

var a = {}, b=a;
a = {some:1};
alert(b.some);

That won't work, cause in line a={some:1} you are losing your link to b.
Hope it'll make sense!

Comments

0

There are an objects in memory and there are adresses of this objects. Your variable obj contains address to object. When you assign obj variable to obj property you assign address. Then you overwrite address in obj variable to another object, but in obj property address is still the same.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.