(Revealing) Module Pattern, public variables and return-statement
Asked Answered
A

3

6

I'm trying to understand how public` properties in the (Revealing) Module Pattern work. An advantage pointed out by Carl Danley "The Revealing Module Pattern" is:

Explicitly defined public methods and variables which lead to increased readability

Let's take a look at this code (fiddle):

var a = function() {
    var _private = null;
    var _public = null;
    function init() {
        _private = 'private';
        _public = 'public';
    }
    function getPrivate() {
        return _private;
    }
    return {
        _public : _public,
        init : init,
        getPrivate : getPrivate,
    }
}();

a.init();
console.log( a._public ); // null
console.log( a.getPrivate() ); // "private"

It returns null when calling a._public. I now can manipulate that public property, like a._public = 'public';. But I can't change it from within my object. Or at least those changes aren't passed through. I was kinda expecting it to be "public" as it was updated by the init-method before.

Does this actually mean, that I can't have any methods, that handle public properties? Then public properties in this pattern make little sense, right? I also tried this without luck (fiddle):

return {
    _pubic : _public,
    init2 : function() {
        _public = 'public';
    }
}

Last, but not least, I have a question regarding the whole return statement. Why isn't it possible to just use return this; to make everything public? As this should be the context of the self-invoked function, shouldn't it just return eveyrthing in it? Why do I have to create another object, that is returned? In this fiddle it returns the window object.

Aalesund answered 30/5, 2015 at 11:13 Comment(0)
P
9

Does this actually mean, that I can't have any methods, that handle public properties?

No, it means that you cannot have public variables. var _public is a variable, and it is not accessible from outside, and when you modify the private variable this will not be reflected in your public ._public property.

If you want to make things public, use properties:

var a = function() {
    var _private = null;
    function init() {
        _private = 'private';
        this._public = 'public';
    }
    function getPrivate() {
        return _private;
    }
    return {
        _public : null,
        init : init,
        getPrivate : getPrivate,
    }
}();

I can manipulate that public property, like a._public = 'public';. But I can't change it from within my object.

You can use this in the methods of your object, as shown above. Or you use a to reference the object, or possibly even store a local reference to the object you return. See here for the differences.

Or at least those changes aren't passed through

Yes, because variables are different from properties (unlike in some other languages like Java, and with exceptions for global ones). When you export public: _public in your object literal, it takes only the current value from the _public variable and creates a property on the object with it. There is no persistent reference to the variable, and changes to one are not reflected in the other.

Why isn't it possible to just use return this; to make everything public? As this should be the context of the self-invoked function, shouldn't it just return eveyrthing in it?

Variables are part of a scope in JavaScript. (Except for the global one) those scopes are not objects accessible to the language.

The this keyword does not refer to this scope of the function, but to the context that was provided by the call. That can be the base reference in a method call, the new instance in a constructor invocation, or just nothing in a basic function call like yours (or the global window object in loose mode).

Placida answered 30/5, 2015 at 11:19 Comment(2)
@T.J.Crowder: Thanks for your confidence :-) Actually I went for lunch right after posting this stub, seeing that you already had answered… Unfortunately you have deleted your answer, and its content is not even preserved in the history :-/Placida
Yeah, I saw his answer too and it had some nice insights as well. But suddenly it was gone.Aalesund
H
6

In your module definition, _public is copied by value, because in javascript, only objects are assigned by reference. After that it has no link to the local _public variable whatsoever. This would therefore only work if you either "box" the _public in an object, so it gets copied by reference, or you refer to the object's property within your module as well, having only one reference to the local variable:

var a = function() {
    var module = {
        _public: null
    };

    // use module._public here 

    return module;
}();

a._public = "foo";
Hinterland answered 30/5, 2015 at 11:22 Comment(1)
Seems like a cool trick to box things into objects. Thanks.Aalesund
N
0

You can use this construction for creating new class

function a(){
    var _private = null;
    this.public = null;
    this.getPrivate = function(){
        return _private;
    };

    function init(){
        _private  = "private";
        this.public = "public";
    }

    init.apply(this, arguments);
}

//static function
a.create = function(){
    return new a();
};

//using
var b = new a();
//or
var b = a.create();
Nasopharynx answered 30/5, 2015 at 12:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.