Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Private members in module pattern, not mutable?

function modify(val, newVal) {
    val = newVal;
}
constructorFunc = function () {
    var _private = false;

    return {
        modifyPrivate: function(toVal) {
            return modify(_private, toVal);  // LINE REFERRED TO BELOW AS X
        }
    };
}
var x = constructorFunc(); 
x.modifyPrivate(true); 
x.modifyPrivate(true);  // _private still starts off as false, meaning it wasn't set to true

The one question I have is why the second time I call x.modifyPrivate(true) why is it that when line X is run, the value of _private passed in is still 'false'.

I can make sense of this if I modify my knowledge of closures slightly to be that the closure is done by reference, and when you change the value of a reference you are not chaning the value the original reference pointed to, you are changing the reference itself to point to some new value... But this whole thing is very confusing and I'm sure someone out there can point me to a diagram on the net that explains this.

I'm also very interested in knowing how to write this code so that _private is in fact modified for the subsequent calls to modify().

like image 269
JayPrime2012 Avatar asked Oct 22 '22 21:10

JayPrime2012


1 Answers

JavaScript always passes by value, so there's no way to pass a variable to a function and have the function assign a new value to it as you tried to do.

The modify function is actually not needed at all. Just do this:

constructorFunc = function () {
    var _private = false;

    return {
        modifyPrivate: function(toVal) {
            _private = toVal;
            return this; 
        }
    };
}
var x = constructorFunc(); 
x.modifyPrivate(true); 

The method modifyPrivate has access to the private _private, since it was defined in an inner scope. It's returning this as suggested by raina77ow, so you can chain another method call of x if you wish (e.g. x.modifyPrivate(true).foo(), if you define foo like you did for modifyPrivate).


Now, if you really need to modify the value from an external function that doesn't have access to that scope, you can wrap you private value in an object, and pass the object. In this case, the passed value will be a reference to the object, so modifying its properties would work (note that you can't reassign to the object, just manipulate the properties):

function modify(valObj, newVal) {
    valObj.val = newVal;
    // return whatever is apropriate
}
constructorFunc = function () {
    var _private = {
        val : false
    };

    return {
        modifyPrivate: function(toVal) {
            return modify(_private, toVal);
        }
    };
}
var x = constructorFunc(); 
x.modifyPrivate(true); 
like image 83
bfavaretto Avatar answered Nov 03 '22 04:11

bfavaretto