thedarklord47
thedarklord47

Reputation: 3312

Javascript: Generic getter/setter for revealing module pattern

Basically what I am trying to do is write a re-useable getter/setter to expose variables using the module pattern

// the getter/setter
function pub (variable) {
    return function (value) {
        return (arguments.length ? variable = value : variable);
    }
}

var module = (function () {

    var publicVariable = 0;

    function test () {
        return publicVariable;
    }

    return {
        publicVariable: pub(publicVariable),
        test: test
    }
})();

The desired result is the following:

module.publicVariable();      // 0
module.publicVariable(1);     // 1
module.publicVariable();      // 1
module.test();                // 1

But instead I get:

module.publicVariable();      // 0
module.publicVariable(1);     // 1
module.publicVariable();      // 1
module.test();                // 0

I assume this is because the following line passes the current value of publicVariable to pub, therefore the only closure created is the one inside pub and there is no link to the variable itself.

publicVariable: pub(publicVariable),    // same as "pub(0)"

I know there is no way to pass by reference in javascript. So how else can I accomplish what I am trying to do? I do not care whether props are called by function or property.

i.e. either of the following are fine

module.publicVariable = "new value";
module.publicVariable("new value");

I am just getting really tired of writing:

function prop1f (value) {  return (arguments.length ? prop1 = value : prop1); }
function prop2f (value) {  return (arguments.length ? prop2 = value : prop2); }
function prop3f (value) {  return (arguments.length ? prop3 = value : prop3); }

return {
    prop1: prop1f,
    prop2: prop2f,
    prop3: prop3f
}

as this gets unruly quick on large projects with lots of user accessible properties.

Upvotes: 2

Views: 3181

Answers (1)

Ismail RBOUH
Ismail RBOUH

Reputation: 10460

The problem is that this code:

function pub (variable) {
    return function (value) {
        return (arguments.length ? variable = value : variable);
    }
}

can work perfectly as a getter, but as setter: if you change the parameter itself (variable), that won't affect the item that was fed into the parameter. But if you change the internals of the parameter, that will propagate back.

Instead you can use javascript getters/setters:

var module = (function () {

    var publicVariable = 0;

    function test () {
        return publicVariable;
    }

    return {
        set publicVariable (value) {
            publicVariable = value;
        },
        get publicVariable () {
            return publicVariable;
        },
        test: test
    }
})();

module.publicVariable = 'New value';
console.log(module.publicVariable);

Demo:

var module = (function () {

    var publicVariable = 0;

    function test () {
        return publicVariable;
    }

    return {
    	set publicVariable (value) {
            publicVariable = value;
        },
        get publicVariable () {
        	return publicVariable;
        },
        test: test
    }
})();

module.publicVariable = 'New Value';
console.log(module.publicVariable);
console.log(module.test());

Another generic alternative:

var module = (function () {

    var publicVariable = 0;

    function test () {
        return publicVariable;
    }

    return {
        //This function can access `publicVariable` !
        publicVariable: function(value) {
            return (arguments.length ? publicVariable = value : publicVariable);
        },
        test: test
    }

})();

module.publicVariable('new Value');
console.log(module.publicVariable());

Demo:

var module = (function () {

    var publicVariable = 0;
    
    function test () {
        return publicVariable;
    }

    return {
        //This function can access `publicVariable` !
    	publicVariable: function(value) {
        	return (arguments.length ? publicVariable = value : publicVariable);
        },
        test: test
    }
    
})();

module.publicVariable('new Value');
console.log(module.publicVariable());

Upvotes: 5

Related Questions