0

This is from an example in YDKJS Scope & Closures:

   var foo = (function CoolModule(id) {
        function change() {
            // modifying the public API
            publicAPI.identify = identify2;
        }
        function identify1() {
            console.log(id);
        }
        function identify2() {
            console.log(id.toUpperCase());
        }
        var publicAPI = {
            change: change,
            identify: identify1
        };
        return publicAPI;
    })("foo module");
    
    foo.identify(); // foo module
    foo.change();
    foo.identify(); // FOO MODULE

Inside of the function change(), I'm modifying the content of the returned object by assigning a different function to the "identify" key. Indeed, I can change the value of any key to any value like this: for example, publiAPI.change = null; I can even add new properties this way, e.g., publicAPI.newFunc = function(){console.log("hi");}. However, I cannot do publicAPI = {} or set the publicAPI object itself, e.g., publicAPI = {a: 1}. Why is this the case? Is there a way to modify the object itself? I can even use the delete operator to delete properties.

univuniv1
  • 63
  • 5
  • [Related](//google.com/search?q=site%3Astackoverflow.com+js+assignment+to+object+does+not+change+original+value) to [Is JavaScript a pass-by-reference or pass-by-value language?](/q/518000/4642212) and [Value of variable not getting updated after assignment](/q/44208998/4642212). – Sebastian Simon Jun 21 '21 at 04:48

1 Answers1

3

However, I cannot do publicAPI = {} or set the publicAPI object itself, e.g., publicAPI = {a: 1}.

Yes, you can. It just has no effect at all on foo.

Why is this the case?

Because when you do:

return publicAPI;

what's returned is the value of publicAPI, not a reference to the variable. That value is the object reference. If you change the value that's in the publicAPI variable later, that has no effect on anything that has received the previous value of the variable.

Is there a way to modify the object itself?

Your example of assigning to the identify property changes the object (e.g., changes the state of one of the object's properties). But the only way to change which object foo refers to is to assign to foo. Nothing you do to publicAPI can change what object foo refers to.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • I thought objects are treated/passed around/returned as references in JS. Is that wrong? Also, I don't understand why according to your answer, publicAPI.property = someValue does have an effect on foo when publicAPI = { ... } doesn't. – univuniv1 Jun 20 '21 at 22:07
  • @univuniv1 *Objects* are, not variables. When you do `a = someObject; b = a;` the object reference that was in `a` is copied to `b` and so both `a` and `b` refer to the same object. But there's no link between the variables `a` and `b`, they just both happen to contain the same value (an object reference to some object). If you do `a = someOtherObject;`, that has no effect on `b`, it just changes what object `a` refers to. It's exactly like `a = 5; b = a; a = 7;` The fact you've assigned `7` to `a` has no effect on `b`, `b` still contains `5`. – T.J. Crowder Jun 20 '21 at 22:12
  • *"Also, I don't understand why according to your answer, publicAPI.property = someValue does have an effect on foo when publicAPI = { ... } doesn't."* Because in that case, you're changing the state of the object that both `foo` and `publicAPI` refer to, not *which object* they refer to. – T.J. Crowder Jun 20 '21 at 22:12
  • Okay, I understood _that_ immediately. I'm still struggling to see how it pertains to my question. Are you basically saying that when I return an object and link it up with foo, that further changes to the publicAPI variable inside the module won't affect foo? If this is the case, is there no better way to turn _the publicAPI that foo refers to_ into an empty object than by deleting its properties? Edit: This comment was in response to your previous comment about a = someObject... etc. – univuniv1 Jun 20 '21 at 22:16
  • @univuniv1 - Once you return the value in `publicAPI` from the function and assign it to `foo`, there is nothing you can do from the code inside that function to change what value `foo` contains (that is, what object `foo` refers to) other than assigning to `foo` (by name). You can change the state of that object by assigning to or removing properties from it (via either `publicAPI` or `foo`, doesn't matter, they both refer to the same object), but you can't change *which object* `foo` refers to. – T.J. Crowder Jun 20 '21 at 22:19
  • I understand completely now, changing what the _name_ publicAPI refers to does not change what foo refers to. Changing the object itself does change what foo refers to. – univuniv1 Jun 20 '21 at 22:29