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.
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.
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.
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:
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.
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).
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";
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With