1

I was playing around with some design-patterns (Module Reveal and Singleton patterns) with basic stuff that worked as expected, like two utility functions that are shared with multiple objects, having one of them update the value of a String and the other copy a value of a String.

The unexpected thing happened when I turned the String to an Array, expecting it to get passed by reference, which it didn't for some reason:

Test.js

(function(win){
    var MainObj=(function(){
        var _alls = Object.create(null);

        function u_updateVal(){
            this.arr = ["up", "da", "ted"];
        }

        function u_copyVal(oName, prop){
            this[prop] = _alls[oName][prop];
        }

        function init(oName){
            if(typeof _alls[oName]==="undefined"){
                _alls[oName] = {
                    arr : ["def", "ault"],
                    updateVal : u_updateVal,
                    copyVal : u_copyVal
                };
            }

            return _alls[oName];
        }

        return {
            init : init
        };
    })();

    if(!win.MainObj){
        win.MainObj = MainObj;
    }
})(window);

plain-js from the HTML, depends on: Test.js

if(!window.MainObj){
    console.log("Error: MainObj is not defined");
}else{
    var a = MainObj.init("AA");
    var b = MainObj.init("BB");
    var c = MainObj.init("CC");

    b.updateVal();
    c.copyVal("BB", "arr");
    b.arr=["over", "written"];

    console.log(a.arr.join()); //def,ault
    console.log(b.arr.join()); //over,written
    console.log(c.arr.join()); //up,da,ted (I expected "over,written")
}

I expected c.arr to point at the same reference of b.arr since the copy from of the Array didn't had any precautions like splice/slice/JSONstringify/etc.

In an attempt to change things, I created another function to update the value via b.otherUpdateVal(); instead of b.arr = ["over", "written"];, in hope it had something to do with a Closure thing beyond my current understanding of them, but this still gives the same result.

I can't seem to understand why these Arrays are not getting passed by reference (even though no special measures were taken to prevent this). Any thoughts why this might be happening?

EDIT: yep, this was just a silly oversight of thinking reassigning b would affect the already done reference of c. If you use b.arr.push("."); or sort, or anything that actually doesn't create a whole new Array, you do see both of them getting affected.

ajax333221
  • 11,436
  • 16
  • 61
  • 95
  • In what circumstances would you expect assigning a value to a property on one object to affect a property on a *different* object (ignoring obviously setter functions)? – Pointy Dec 26 '18 at 21:24
  • Oops, my bad for not paying attention to what language that question was about. And StackOverflow's bad for saying it was the top related question. Should have been this one https://stackoverflow.com/questions/518000/is-javascript-a-pass-by-reference-or-pass-by-value-language?rq=1 – Herohtar Dec 26 '18 at 21:24
  • @Pointy I actually don't, this was just a mistake from me – ajax333221 Dec 26 '18 at 21:24
  • OK, well `b.arr = []` assigns a new value to the "arr" property of the object `b`. – Pointy Dec 26 '18 at 21:25
  • 1
    that's why better to use functional programing :) – The Reason Dec 26 '18 at 21:29
  • @Pointy do you think I should delete this question? It seems like it won't help anyone in the future, and it's not even a real duplicated. I voted to close as offtopic but I think this is just garbage that should totally be destroyed from earth leaving the least trace of its existence. – ajax333221 Dec 26 '18 at 21:45
  • lol well it won't hurt my feelings either way :) – Pointy Dec 26 '18 at 21:48
  • the system did't let me, anyway, it's a good reminder that sometimes small pebbles can sprain ankles too – ajax333221 Dec 26 '18 at 22:09
  • @TheReason why, does the assignment operator work any different when you use FP in JS? – Thomas Dec 26 '18 at 22:35

2 Answers2

2

Let's step through what happens.

var a = MainObj.init("AA");
var b = MainObj.init("BB");
var c = MainObj.init("CC");

After this step you have.

a.arr; // ["def", "ault"]
b.arr; // ["def", "ault"]
c.arr; // ["def", "ault"]

Then we change b.

b.updateVal();

The rest stay the same, and b has updated.

b.arr; // ["up", "da", "ted"]

You then assign the same b.arr reference to c.arr in you copyVal function.

this[prop] = _alls[oName][prop]; // Copy the reference.

Your final change creates a whole new array and assigns it to b.

b.arr=["over", "written"];

And you get.

a.arr; // ["def", "ault"]
b.arr; // ["over", "written"] a new array you've created in the final step.
c.arr; // ["up", "da", "ted"] which is the old b array still being referenced.
Morgan Wilde
  • 16,795
  • 10
  • 53
  • 99
1

After this:

c.copyVal("BB", "arr");

the values of the "arr" properties of both b and c will be references to the same array. After this, however:

b.arr=["over", "written"];

you've overwritten the value of the "arr" property. That does not have any effect on the value of c.arr.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • 1
    Note that as far as I can tell the confusion in the question has nothing to do with "passing" anything; it's just normal assignment operator behavior. – Pointy Dec 26 '18 at 21:22
  • I don't know whats happening to me today lol, so silly mistake – ajax333221 Dec 26 '18 at 21:26