hey guys i am just trying to understand the REVEALING MODULAR PATTERN, i see the following simple depiction of the revealing modular pattern:
var myRevealingModule = (function () {
var privateCounter = 0;
function privateFunction() {
privateCounter++;
}
function publicFunction() {
publicIncrement();
}
function publicIncrement() {
privateFunction();
}
function publicGetCount(){
return privateCounter;
}
// Reveal public pointers to
// private functions and properties
return {
start: publicFunction,
increment: publicIncrement,
count: publicGetCount
};
})();
myRevealingModule.start();
now the following disadvantages are stated of the revealing moduar pattern ::
A disadvantage of this pattern is that if a private function refers to
a public function, that public function can't be overridden if a patch
is necessary. This is because the private function will continue to
refer to the private implementation and the pattern doesn't apply to
public members, only to functions.
i don't quite understand what the above para means , can somebody explain ? private function refers to the public function , did't quite get that , can somebody break it down ?
Consider:
Mod = function() {
function inc() {
return value() + 1;
}
var value = function() { return 42 }
var valuePlusOne = function() { return inc() }
return {
value: value,
valuePlusOne: valuePlusOne
}
}()
document.write(Mod.valuePlusOne()) // 43
Mod.value = function() {
return 999
}
document.write(Mod.valuePlusOne()) // still 43, not 1000
The problem is that inc uses var value from its containing scope, not the value property of the module object. When you change the module, this doesn't affect var value from the scope.
A workaround is to bind private functions to the object being returned:
Mod = function() {
var value = function() { return 42 }
var valuePlusOne = function() { return inc() }
var me = {
value: value,
valuePlusOne: valuePlusOne
}
function inc() {
return me.value() + 1;
}
return me;
}()
document.write(Mod.valuePlusOne()) // 43
Mod.value = function() {
return 999
}
document.write(Mod.valuePlusOne()) // 1000
Related
Do I use correctly simulation of private variable with this way?
var C = function(a) {
var _private = a + 1;
// more code...
Object.defineProperties(this, {
'privateProp': {
get: function() {
return _private;
},
set: function(b) {
_private = b + 2;
}
}
});
}
So with the getter/setter I can manage that private variable. And value of it can be get/set with custom methods.
Let's say this example
var c = new C(5);
console.log(c.privateProp); // 6
c.privateProp = 2;
console.log(c.privateProp); // 4
There is no correct way to simulate private variables, because they are not part of the Javascript specification.
However, there are still a number of ways to simulate them:
With Getters and Setters
This is the same as your answer but with a slightly different syntax:
function Rocket() {
var _fuel = 100;
return {
get fuel() {
return _fuel;
}
set fuel(value) {
_fuel = value;
}
};
}
This syntax allows you to define the getter and setter functions in a more natural way, but comes with the restriction that they must be inside an object literal.
With a Closure
function Rocket() {
var fuel = 100;
return {
getFuel: function() { return fuel; },
setFuel: function(value) { fuel = value; }
};
}
This is arguably the most elegant way, because this is how Javascript has worked ever since anonymous functions were added to the specification.
By Convention
function Rocket() {
this._fuel = 100;
this.getFuel = function() {
return this._fuel;
};
this.setFuel = function(value) {
this._fuel = value;
};
}
The final way is to expose the variable as public, but mark it as private by using an underscore at the beginning of the name.
Is it possible to have private properties in a model? Like the locally declared variables in a (constructor) function, not attached to this, but declared locally and visible only by whatever is defined in the (constructor)function.
Example without BB View:
function MyView(aModel){
var $internalInput = $('<input>');
this.render: function($where){
$internalInput.val(aModel.get('SomeProperty'));
$where.append($('<div class="inputWraper">').append($internalInput));
};
this.toggleReadonly: function() {
toggle $internalInputs readonly attribute
}
...
+ Code to bind input.val to some aModel property(ies) and setup events
...
}
Note that internalInput is not accessible to outside world and aModel is also not accessible (through MyView at least).
So if I want to use Backbone.View to implement the above MyView, how would i do it and keep $internalInput 'private'?
You should be able to achieve private data by passing an IIFE to extend when defining your Backbone objects, rather than just a plain object. For example:
var Thing = Backbone.Model.extend((function () {
var foo = "Private data!";
return {
bar: function () {
console.log(foo);
}
};
})());
You'd better off with
var Thing = Backbone.Model.extend(
{
constructor : function ()
{
var _value = "Private data!";
this.getValue = function ()
{
return _value;
};
this.setValue = function (value)
{
_value = value;
};
}
});
Javascript is fun!
var Thing = (function () {
var number_of_things = 0;
return function (options) {
var value = "Private data!";
return new ( Backbone.Model.extend({
constructor: function constructor () {
number_of_things += 1;
},
getValue: function getValue () {
return value;
}
}) )();
};
}());
I'm a little concerned by the fact that every instance of this "Thing" is also a subclass, in the OOP lingo.
In the context of using Broserify.js with Backbone (and really any above medium project) I found the following way to have private vars and functions:
myView.js
'use strict';
var config = require('../config.js'),
private_var = 'private variable',
my_private_fn = function() {
...
};
module.exports = Backbone.Model.extend({
initialize: function() {
this.my_public = 'public variable');
console.log('This is my' + this.my_public);
console.log('This is my' + my_private);
},
});
The idea to take here is go with Browserify :P
The simplest way is the following:
...
initialize:function(properites){
// Init the logic with private and public methods/variable
this.logic.initFirst(this);
// Use public methods
this.logic.doSomething();
},
logic:{
initFirst:function(modelOrView){
// Do not continue if already initiated
if( this.instance !== undefined ) return;
// Write all logic here
this.instance = (function(logic, modelOrView){
// Private variables
var private = "private";
// Public methods
logic.doSomething = function(){
console.log(private, modelOrView);
};
// Private methods
function hidden(){
}
}(this, modelOrView));
}
},
I have tree of closures: 'A' containing private closures 'pancake' and 'B'. There is a situation when I need to call from inside of 'B' public function, the private closure of 'A' - 'pancake' and retrieve its public properity. How can I do it? Oh, and this is useless, as this is not an object.
My code:
var A = (function() {
var pancake = (function() {
return {
numeric: 142
};
})(A);
var B = (function() {
return {
init: function(name) {
console.log(pancake.numeric);
//How to access the same element using 'name' variable?
}
};
})(A);
return {
init: function() {
B.init('pancake');
}
};
})();
A.init();
JSFiddle might show more details: http://jsfiddle.net/yALkY/3/
Thanks in advance
Though I have to aggree with jfriend00 that the given code is over-complicating things, one solution would be to introduce some map to store references in, like:
var A = (function() {
var pancake = (function() {
return {
numeric: 142
};
})();
var B = (function() {
return {
init: function(name) {
console.log(privateVars[name].numeric);
//How to access the same element using 'name' variable?
}
};
})();
// added:
var privateVars = {
pancake: pancake
};
return {
init: function() {
B.init('pancake');
}
};
})();
A.init();
The drawback, of course, is that you'll have to maintain that list manually.
I was experimenting with some examples and came across a problem that if we want to add a function to a prototype it will not be able to access the private members of the constructor. I came across this solution. This seems to be a nice hack.
I tried out some other ways and I got the following:
var Restaurant = function()
{
var myPrivateVar;
var private_stuff = function() // Only visible inside Restaurant()
{
return "I can set this here!";
}
Restaurant.prototype.use_restroom = function() // use_restroom is visible to all
{
private_stuff();
}
Restaurant.prototype.buy_food = function() // buy_food is visible to all
{
return private_stuff();
}
}
var restaurant = new Restaurant();
restaurant.buy_food(); // this would work
restaurant.private_stuff(); // this won't
The solution seems weird because we are adding to the prototype within the constructor function. (I haven't seen much of this). It works on firefox 5 and chrome at least. Is there something wrong with it?
What you're doing is redefining those methods on the prototype every time you make a new restaurant object. The more sane way to do that would be to define them on this, which is the new object being constructed in a constructor:
var Restaurant = function()
{
var myPrivateVar;
var private_stuff = function() // Only visible inside Restaurant()
{
return "I can set this here!";
}
this.use_restroom = function() // use_restroom is visible to all
{
private_stuff();
}
this.buy_food = function() // buy_food is visible to all
{
return private_stuff();
}
}
You could just do it like this though, and not use new:
var RestaurantMaker = function () {
var myPrivateVar;
var private_stuff = function() {
return "I can set this here!";
}
return {
use_restroom: function () {
private_stuff();
},
buy_food: function () {
return private_stuff();
}
};
}
and then just do:
var restaurant = RestaurantMaker();
This is called the revealing module pattern. The downside is that each new object gets a copy of all the functions, which also happens if you add methods to this in your constructor.
A very small alternative version of the revealing module pattern (which I think reads a bit better) looks like this:
var RestaurantMaker = function () {
var myPrivateVar;
function private_stuff() {
return "I can set this here!";
}
function use_restroom() {
private_stuff();
}
function buy_food() {
return private_stuff();
}
return {
use_restroom: use_restroom,
buy_food: buy_food
};
}
Then, if you want to change whether a function is private or not, it's just a matter of adding or removing it from the returned object.
I didn't actually test this, but I think all the objects would access to the last instantiated object's private properties.
On each instantiation you're binding the prototype methods (shared across all instances) to the private variables of the object being instantiated :)
Honestly, it doesn't make a lot of sense to me. Sure, you can have calls to your private functions this way, but it doesn't solve the initial problem - that is, you still need to add methods inside the constructor.
If you want to add methods to the class outside the constructor, you can use closures to keep constructors clean:
// Creating a closure inside a self-calling function
var Restaurant = (function() {
// Only visible inside this closure
var myPrivateVar;
var private_stuff = function() {
return "I can set this here!";
}
var Restaurant = function() {};
// use_restroom is visible to all
Restaurant.prototype.use_restroom = function() {
private_stuff();
};
// buy_food is visible to all
Restaurant.prototype.buy_food = function() {
return private_stuff();
};
// We give back the Restaurant-constructor to the people
return Restaurant;
})();
var restaurant = new Restaurant();
restaurant.buy_food(); // this would work
restaurant.private_stuff(); // this won't
We take a different approach. We do use closures sometimes, but only when you need to manage state at the class level. We use namespaces to manage scope. For a simple class with prototype methods, we just do this:
/**
* #namespace
*/
var chain = {};
(function () {
/**
* The constructor is used to manage private data
* #constructor
*/
chain.Restaurant = function () {
// Only visible inside this constructor
var inventory = { };
/**
* add an item with a count to the inventory
* This is a privileged function.
* #param {String} item The identifier for the item you are adding
* #param {String} count The count you are adding for the item.
*/
this.addInventory = function (item, count) {
if (count < 0) {
// throw an error
}
var current = this.getInventory(item);
inventory[item] = current + count;
}
// privileged function
this.getInventory = function (item) {
if (inventory.hasOwnProperty(item)) {
return inventory[item];
}
return 0;
}
// privileged function
this.removeInventory = function (item, count) {
throwIfNegative(count);
if (this.getInventory(item) < count) {
throw new Error("Inventory Unavailable");
}
inventory[item] -= count;
}
// private function, only visible to the privileged functions
function throwIfNegative (value) {
if (value < 0) {
throw new Error("Negative Inventory Is Not Valid");
}
}
}
// member/prototype method
chain.Restaurant.prototype.sellInventory = function (item, count) {
var availabe = this.getInventory(item);
var sellCount = Math.min(available, count, 0);
if (sellCount > 0) {
// do this conditionally if there are implications to invoking the functions
this.removeInventory(sellCount);
sellItem(item, sellCount);
}
return sellCount;
}
// member/prototype method
chain.Restaurant.prototype.hasInventory = function (item, count) {
return this.getInventory(item) >= count;
}
// namespace method
chain.soldQuantity = function (item) {
if (!itemsSold.hasOwnProperty(item)) {
return 0;
}
return itemsSold[item];
}
// functions defined in this closure can see this
var itemsSold = { };
// all functions defined in this closure can call this
function sellItem (item, quantity) {
if (!itemsSold.hasOwnProperty(item)) {
itemsSold[item] = 0;
}
itemsSold[item] += quantity;
}
})();
Is there a way to get all methods (private, privileged, or public) of a javascript object from within? Here's the sample object:
var Test = function() {
// private methods
function testOne() {}
function testTwo() {}
function testThree() {}
// public methods
function getMethods() {
for (i in this) {
alert(i); // shows getMethods, but not private methods
}
}
return { getMethods : getMethods }
}();
// should return ['testOne', 'testTwo', 'testThree', 'getMethods']
Test.getMethods();
The current issue is the code in getMethods(), the simplified example will return just the public methods, but not to private ones.
edit: my test code may (or may not) be overcomplicating what i'm hoping to get at. given the following:
function myFunction() {
var test1 = 1;
var test2 = 2;
var test3 = 3;
}
is there a way to find out what variables exist in myFunction() from within myFunction(). the pseudo-code would look like this:
function myFunction() {
var test1 = 1;
var test2 = 2;
var test3 = 3;
alert(current.properties); // would be nice to get ['test1', 'test2', 'test3']
}
The technical reason why those methods are hidden is twofold.
First, when you execute a method on the Test object, "this" will be the untyped object returned at the end of the anonymous function that contains the public methods per the Module Pattern.
Second, the methods testOne, testTwo, and testThree aren't attached to a specific object, and exist only in the context of the anonymous function. You could attach the methods to an internal object and then expose them through a public method, but it wouldn't be quite as clean as the original pattern and it won't help if you're getting this code from a third party.
The result would look something like this:
var Test = function() {
var private = {
testOne : function () {},
testTwo : function () {},
testThree : function () {}
};
function getMethods() {
for (i in this) {
alert(i); // shows getMethods, but not private methods
}
for (i in private) {
alert(i); // private methods
}
}
return { getMethods : getMethods }
}();
// will return ['getMethods', 'testOne', 'testTwo', 'testThree']
Test.getMethods();
edit:
Unfortunately, no. The set of local variables aren't accessible via a single, automatic keyword.
If you remove the "var" keyword they would be attached to the global context (usually the window object), but that's the only behavior that I know of that is similar to what you're describing. There would be a lot of other properties and methods on that object if you did that, though.
From http://netjs.codeplex.com/SourceControl/changeset/view/91169#1773642
//Reflection
~function (extern) {
var Reflection = this.Reflection = (function () { return Reflection; });
Reflection.prototype = Reflection;
Reflection.constructor = Reflection;
Reflection.getArguments = function (func) {
var symbols = func.toString(),
start, end, register;
start = symbols.indexOf('function');
if (start !== 0 && start !== 1) return undefined;
start = symbols.indexOf('(', start);
end = symbols.indexOf(')', start);
var args = [];
symbols.substr(start + 1, end - start - 1).split(',').forEach(function (argument) {
args.push(argument);
});
return args;
};
extern.Reflection = extern.reflection = Reflection;
Function.prototype.getArguments = function () { return Reflection.getArguments(this); }
Function.prototype.getExpectedReturnType = function () { /*ToDo*/ }
} (this);
Javascript doesn't really have the notion of private anything. Because of that, javascript doesn't have a reflection API as such. The technique you're using doesn't so much make them private as render them inaccessible; they're hidden, not private. I think you could manage something by putting those methods somewhere manually.
Part of the issue with your test code is that Test is the object created by your return statement: "{ getMethods : getMethods }" It has no testOne, testTwo, or testThree methods; instead, those are only available within the same namespace as the original getMethods function.
With a little change to the way the function is defined you can achieve what you want. Wrap the actual implementation of the function in an object literal it would then look like this:
(function() {
var obj = {
// private methods
testOne: function () {},
testTwo : function () {},
testThree: function () {},
// public methods
getMethods : function () {
for (i in this) {
alert(i); // shows getMethods, but not private methods
}
}
};
return { getMethods : function(){return obj.getMethods();} }
})();
you can use var that = this; trick:
var Test = function() {
var that = this;
function testOne() {}
function testTwo() {}
function testThree() {}
function getMethods() {
for (i in that) {
alert(i);
}
}
return { getMethods : getMethods }
}();
If you call getMethods() like that, isn't it static? Surely you'd need to properly init the class for this to work as expected?
var t = new Test();
t.getMethods();
If that doesn't work, please take a look at the JS Serializer. I used it a while back for some debug and I think it worked for private vars.