Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 716
lampshade Avatar asked May 30 '15 11:05

lampshade


People also ask

What is the difference between a module and a revealing module?

The revealing module pattern is really almost the same as the module pattern. The major difference to be aware of is simply how the revealing module pattern exposes it’s api. In other words, what is contained in the return statement of the revealing module pattern is different than what is in the module pattern.

What is the revealing module pattern in JavaScript?

To be fair, the revealing module pattern is very similar to the module pattern, but it has a really nice way of exposing the api of a module to it’s users or consumers. I think you’ll find the revealing module pattern to be a really good balance of how to structure your JavaScript code for readability.

What is the purpose of the module pattern?

The module pattern allows for public and private (plus the lesser-know protected and privileged) access levels. Modules should be Immediately-Invoked-Function-Expressions (IIFE) to allow for private scopes - that is, a closure that protect variables and methods (however, it will return an object instead of a function). This is what it looks like:

Is a new keyword required with a revealing module pattern?

This is not an actual requirement, but it is a good idea from a conventions standpoint, as it gives an indication that the new keyword is not required with the revealing module pattern. The reason no new keyword is required is because of those two little parenthesis after the function declaration. This means it is a self-calling function.


2 Answers

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

like image 116
Bergi Avatar answered Oct 06 '22 13:10

Bergi


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";
like image 5
Gerard van Helden Avatar answered Oct 06 '22 14:10

Gerard van Helden