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