Javascript simulate real private variable and manage it with getter/setter - javascript

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.

Related

Trying simple approach to OPP inheritance in Javascript (ES5)

Just for the sake of curiosity, I was playing with prototypal inheritance and OOP inheritance in Javascript. Most results involve emulating 'Class' and 'extends' concepts with functions, while others use the prototype and constructors.
I wrote this code:
function Warrior(weaponName) {
var weapon = weaponName;
this.getWeapon = function() {
return weapon;
};
this.setWeapon = function(value) {
weapon = value;
};
this.displayInfo = function() {
return {
"weapon": this.getWeapon(),
};
};
}
function Archer() {
var accuracy = "86%";
this.parent = Archer.prototype; // Inheritance workaround
this.getAccuracy = function() {
return accuracy;
};
this.setAccuracy = function(value) {
accuracy = value;
};
this.displayInfo = function() {
var form = this.parent.displayInfo();
form.accuracy = this.getAccuracy();
return form;
};
}
Archer.prototype = new Warrior("bow");
var w = new Warrior("sword");
var a = new Archer();
console.log(w.displayInfo());
console.log(a.displayInfo());
I made this so when displaying the information from the Warrior class, it shows the object as
{ weapon: "sword" }
And when the information from Archer is shown, the object is:
{ weapon: "sword", accuracy: "86%" }
The "subclass" is taking information from the "superclass" and adding to it. Calling "getWeapon()" or "setWeapon" from Archer also works. The chain goes on without problems, even when I add a third class "Kyudoka" that extends "Archer" and has it's own properties as well.
But comparing to the more complex code I found while researching, I feel this could be a naive implementation (the "Inheritance workaround" line) and I'm missing something (considering that JS has a lot of subtlety).
This is a theorical question, I'm not using this code in any system.
There are mainly 3 kinds of inheritance in javascript, according to the book Javascript the Good Parts: Pseudoclassical, Prototypal and Functional.
The one you just posted would fit under the Pseudoclassical inheritance, where you emulate a Class behaviour using constructor functions.
I find more useful and flexible the Functional pattern, which allows you to protect your variables (make them private).
var constructor = function (spec, my) {
var that, other private instance variables;
my = my || {};
//Add shared variables and functions to my
that = a new object;
//Add privileged methods to that
return that;
}
Prototypal is basically having your objects inherit directly from other useful object, which would be something like having them (the useful objects) as your new object constructor prototype.
Object.beget = function (o) {
var F = function () {};
F.prototype = o;
return new F();
};
var a = {}
//Add shared variables to a
var b = Object.beget(a);
//Add new methods to b
That are many considerations to each of the patterns, for instance Crockford says in his book "The functional pattern has a great deal of flexibility. It requires less effort than the pseudoclassical pattern,
and gives us better encapsulation and information hiding and access to super methods.", but I've also seen articles arguing the other way around, such as this http://bolinfest.com/javascript/inheritance.php
EDIT ------
In case you might want to know different aproaches to reaching super methods, in the Functional pattern you can do the following:
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
Object.method('superior', function (name) {
var that = this,
method = that[name];
return function ( ) {
return method.apply(that, arguments);
};
});
var archer = function (spec, accuracy) {
var that = warrior(spec),
super_displayInfo = that.superior('displayInfo');
that.getAccuracy = function() {
return accuracy;
};
that.setAccuracy = function(value) {
accuracy = value;
};
that.displayInfo = function (n) {
var form = super_displayInfo()
form.accuracy = that.getAccuracy();
return form;
};
return that;
};
Put the functions on the prototype...
function Warrior(weaponName) {
this.weapon = weaponName;
}
Warrior.prototype = {
getWeapon : function() {
return this.weapon;
},
setWeapon : function(value) {
this.weapon = value;
},
displayInfo : function() {
return { "weapon" : this.getWeapon() };
}
};
//----------------------------------
function Archer(weaponName) {
Warrior.call(this, weaponName);
this.accuracy = "86%";
}
Archer.prototype = Object.create(Warrior.prototype);
Archer.prototype.constructor = Archer;
Archer.prototype.getAccuracy = function() {
return this.accuracy;
};
Archer.prototype.setAccuracy = function(value) {
this.accuracy = value;
};
Archer.prototype.displayInfo = function() {
return "weapon: " + this.getWeapon() + ", accuracy: " + this.getAccuracy();
};
//----------------------------------
var w = new Warrior("sword");
var a = new Archer("axe");
console.log(w.displayInfo()); // Object {weapon: "sword"}
console.log(a.displayInfo()); // weapon: axe, accuracy: 86%
Edit: fixed recursion

understanding revealing modular pattern

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

Using "dot" inside a prototype name in JavaScript

Lets say I have this class:
function classA(n){
this.name = n
}
classA.prototype.getName = function(){
return this.name
}
var x = new classA('john')
console.log(x.getName())
My question is: can I group multiple methods inside a namespace? So I would like to do that:
var x = new classA('john')
console.log(x.CONSTANT.getName())
So I would like to call some methods as x.someMethod() and others as x.CONSTANT.otherMethod()
PS: I'm looking for a cross-browser method. Bind is not working in Safari and IE9.
You can do it, for example, via bind. Google es5 shim for implementation of bind in browsers, which don't support it natively.
function MyClass(name) {
this.name = name;
this.CONSTANT.otherMethod = this.CONSTANT.otherMethod.bind(this);
}
MyClass.prototype.CONSTANT = {
otherMethod: function() {
alert(this.name);
}
};
As far as I know a constant is just a property and it can't contain methods, you need to separate your objects and use methods to have the same effect:
function A (id) {
this.id = id;
this.showId = function () { return this.id; }
};
function B (a) {
this.a = a;
this.getA = function () { return this.a; }
}
var a = new A(12);
var b = new B(a);
b.getA().showId();
edit:
You can use a literal object as follow
function B (id) {
this.id = id;
this.CONSTANT = { otherMethod: function () { alert("..."); } };
someMethod = function () { return this.id; }
}
but the literal CONSTANT object can't access B-object methods,
Consider the #kirilloid post to round this.
You can, but you have to be careful because it won't act like you think it will. The this for the method will be the namespace, not the root object.
For example, in x.CONSTANT.getName(), the this object will be x.CONSTANT, and not x.
Here's some sample code which kinda does what you ask (or in jsfiddle):
function MyClass() {}
MyClass.prototype.CONSTANT = {
getName: function() {
alert('Foo');
}
};
var c = new MyClass();
c.CONSTANT.getName();
To make sure the this is right, you need to do much more.
You can use getters/setters (read this article) to achieve this. For example you may define it like this:
classA.prototype.__defineGetter__('CONSTANT', function() {
var that = this;
return {
getName: function() {
return that.name;
}
};
});
Note that holding reference to the object. It will work now
x = new classA('test');
x.CONSTANT.getName();
// result - test

Adding properties to a prototype within the constructor function

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;
}
})();

Neat alternatives to __defineGetter__?

Getters and setters are a beauty in VB.Net:
Get
Return width
End Get
Set(ByVal value As Integer)
width = value
End Set
In Javascript, this is probably what we would do:
function Test() {
var width = 100;
this.__defineGetter__("Width", function() {
return width;
});
this.__defineSetter__("Width", function(value){
width = value;
});
}
It looks like a plate of spaghetti ransacked by a kuri. What are some neater alternatives we have?
Note: The new code should access the value using new Test().Width and not new Test().Width().
With ES5 you'll be able to do:
function Test() {
var a = 1;
return {
get A() { return a; },
set A(v) { a = v; }
};
}
The getter/setter functions can of course do anything you want them to.
Here's a clean(er) alternative (also for older script engines):
function Test() {
var a=1;
return { A: { toString: function(){return a;} } };
}
alert(Test().A); //=> 1
Mind you, you can't use it to define private/static complex structures. You can only 'get' strings or numbers (so immutable variables) with this pattern. Maybe the pattern can be enhanced using json.
[edit] Using json, you can also create a getter this way for objects:
function Test() {
var a=1,
b = {foo:50, bar:100};
return {
A: { toString: function(){return a;} }
foobar: { toString: function(){return JSON.stringify(b);} }
};
}
var foobar = JSON.parse(Test().foobar);
alert(foobar.foo); //=> 50
In Ecmascript5, the 'clean' (and standards compliant) way of doing this is with defineProperty.
function Test() {
var a = 1;
Object.defineProperty(this, "A", {get : function() {
return a;
},
enumerable : true});
}
This assumes that you just want to see how to define a getter. If all you want to do is make instances of Test immutable (a good thing to do where you can), you should use freeze for that:
function Test() {
this.a = 1;
Object.freeze(this);
}

Categories