Javascript and module pattern - javascript

i think i did not understand javascript module pattern.
I just create this module:
var mycompany = {};
mycompany.mymodule = (function() {
var my = {};
var count = 0;
my.init = function(value) {
_setCount(value);
}
// private functions
var _setCount = function(newValue) {
count = newValue;
}
var _getCount = function() {
return count;
}
my.incrementCount = function() {
_setCount(_getCount() + 1);
}
my.degreeseCount = function() {
_setCount(_getCount() - 1);
}
my.status = function() {
return count;
}
return my;
})();
var a = mycompany.mymodule;
var b = mycompany.mymodule;
console.debug(a, 'A at beginning');
console.debug(a, 'B at beginning');
a.init(5);
b.init(2);
console.log('A: ' + a.status()); // return 2 (wtf!)
console.log('B: ' + b.status()); // return 2`
Where is the mistake?
I thought that my code would have returned to me not 2 value, but 5.
What's the reason?

a and b are the exact same objects.
var a = mycompany.mymodule;
var b = mycompany.mymodule;
What you want to do is create two different objects which have the same prototype. Something similar to this:
mycompany.mymodule = (function () {
var my = function () {};
my.prototype.init = function (value) {
_setCount(value);
};
my.prototype.incrementCount = ...
// ...
return my;
}());
a = new mycompany.mymodule();
b = new mycompany.mymodule();
a.init(5);
b.init(2);
For more info, research "javascript prototypal inheritance"

In JavaScript, objects are passed by reference, not copied.
To explain further, here is a simplified version of your code:
var pkg = (function () {
var x = {};
return x;
}());
var a = pkg;
var b = pkg;
You do not create two separate objects but only reference the object pointed at by pkg from both a and b. a and b are exactly the same.
a === b // true
This means that calling a method on a you are ultimately doing the same to b (it points to the same object—x.)
You don't want to use the module pattern for this. You want the usual constructor+prototype.
function Pkg() {
this.count = 0;
};
Pkg.prototype.init = function (count) { this.count = count; };
var a = new Pkg();
var b = new Pkg();
a === b // false
a.init(2);
a.count === 2 // true
b.count === 2 // false

Here is a good read about module pattern.

Related

How can I use attributes directly in methods of Javascript prototype?

I am used to coding with objects in different languages such as Java, Python, …
I have never used JavaScript objects before and I am stuck with a problem: I don't know how to use attributes in methods.
I have done the following but perhaps it's not the correct way:
function test() {
this.un = 1;
this.deux = 2;
this.sum = 1;
add = function() {
this.sum = this.un + this.deux;
}
}
var test = new test();
console.log(test.sum); // res : 1
test.add;
console.log(test.sum); // res : 1 and not 3 as like i want
You have to call add as the method and declare it with this.add, like in the code snipet I posted:
function test() {
this.un = 1;
this.deux = 2;
this.sum = 1;
this.add = function() {
this.sum = this.un + this.deux;
}
}
var obj = new test();
console.log(obj.sum); // res : 1
obj.add();
console.log(obj.sum); // res : 3
function test() {
this.un = 1;
this.deux = 2;
this.sum = 1;
this.add = function() {
this.sum = this.un + this.deux;
}
}
var test = new test();
console.log(test.sum); // res : 1
test.add();
console.log(test.sum); // res : 1 and not 3 as like i want

How can I make privileged JS methods?

I want to be able to call sub-functions that work with private data. Currently I have this:
var myFunction4 = function() {
this.secret1 = 0;
this.secret2 = 0;
var that = this;
this.iterate1 = function(){
return that.secret1++;
}
this.iterate2 = function(){
return that.secret2++;
}
this.addSecrets = function(){
return that.secret1 + that.secret2;
}
return {
iterate1: this.iterate1,
iterate2: this.iterate2,
addSecrets: this.addSecrets,
}
};
The bad thing about this is that to call one of the methods, I have to do:
myFunction4().iterate1();
Which executes myFunction4() every single time I want to access a method. Not only is this inefficient, but it resets secret1 each time so I can't iterate it. I've tried using the new operator, but that exposes secret1 and secret2, and it messes up the ability to nest functions deeply.
var myFunction3 = function() {
this.secret1 = 0;
this.secret2 = 0;
this.iterate1 = function(){
return this.secret1++;
}
this.iterate2 = function(){
return this.secret2++;
}
this.addSecrets = function(){
return this.secret1 + this.secret2;
}
};
var f3 = new myFunction3();
f3.secret1; // exposes the secret!
See the console logs at the bottom of this JSFiddle for more examples.
How can I have a function with both private and public vars/methods which retain their values and don't need to be called multiple times?
While the other answers are absolutely fine and correct, there is one more issue to consider when emulating OOP behaviour in javascript.
The function execution context issue will bite us hard when we will try to use a public method as a e.g. async. callback.
The magical this will point to a different object then we expect in the OOP world.
Of course there are ways to bind the context but why to worry about this after we define the 'class' in a non OOP js ;)
Here is a simple solution to this: Do not use this. Let the closure refactor this out ;)
var myFunction4 = function() {
// we could inherit here from another 'class' (object)
// by replacing `this` with e.g. `new SuperClass()`
var that = this;
// 'private' variables
var secret1 = 0;
var secret2 = 0;
// 'public' variables
that.somePublicVar = 4;
// 'private' methods
var somePrivateMethod = function(){
secret2 = 77;
that.somePublicVar = 77;
}
// 'public' methods
that.iterate1 = function(){
return secret1++;
}
that.iterate2 = function(){
return secret2++;
}
that.addSecrets = function(){
return secret1 + secret2;
}
return that;
};
var f = new myFunction4();
console.log( f.iterate1() ); // 0
console.log( f.iterate1() ); // 1
console.log( f.secret1 ); //undefined
console.log( f.somePublicVar ); //4
Try that (closures power!):
var myFunction3 = function() {
var secret1 = 0;
var secret2 = 0;
this.iterate1 = function(){
return secret1++;
}
this.iterate2 = function(){
return secret2++;
}
this.addSecrets = function(){
return secret1 + secret2;
}
};
var f3 = new myFunction3();
now only the methods are exposeds
Edited version:
If you don't wanna execute the main function every time you call sub-method, you can change a bit your approach and use the power of IIFE (immediately-invoked function expression)
var myFunction4 = (function() {
var secret1 = 0;
var secret2 = 0;
var iterate1 = function(){
return secret1++;
}
var iterate2 = function(){
return secret2++;
}
var addSecrets = function(){
return secret1 + secret2;
}
return {
iterate1: iterate1,
iterate2: iterate2,
addSecrets: addSecrets
}
}());
Then you can use this:
myFunction4.iterate1();
myFunction4.iterate2();
myFunction4.addSecrets();
Hope this helps you
I generally only use the factory pattern to create objects unless I absolutely need to have the performance benefits of prototypical inheritance.
Using the factory pattern also means you don't have to deal with the ever changing value of this in different contexts.
var factory = function() {
// internal private state
var state = {
secret1: 0,
secret2: 0
}
function iterate1(){
return state.secret1++;
}
function iterate2(){
return state.secret2++;
}
function addSecrets(){
return state.secret1 + state.secret2;
}
function __privateMethod() {
// this is private because it's not on the returned object
}
// this is the public api
return {
iterate1,
iterate2,
addSecrets
}
}
// create a secret module
var secret = factory()
console.log(
secret.iterate1(), // 0
secret.iterate2(), // 0
secret.addSecrets(), // 2
secret.secret1, // undefined
secret.secret2 // undefined
)
// you can even create more with the same factory
var secret2 = factory()
Why don't you try Revealing Module Pattern
var myFunction4 = function() {
var secret1 = 0,
secret2 = 0,
iterate1 = function(){
return secret1++;
},
iterate2 = function(){
return secret2++;
},
addSecrets = function(){
return secret1 + secret2;
};
// public functions and properties
return {
iterate1: iterate1,
iterate2: iterate2,
addSecrets: addSecrets,
}
}();
myFunction4.iterate1(); // is available
myFunction4.secret2; // is private and not available outside of myFunction4
Hope it helps
A basic pattern:
var myFunction = function() {
var that = this;
var secret1 = 0;
var secret2 = 0; // private
this.public1 = 0; // public
this.iterate1 = function(){
return secret1++;
}
this.iterate2 = function(){
return secret2++;
}
this.addSecrets = function() { // public
return privateMethod();
}
var privateMethod = function() { // private
return secret1 + secret2;
}
return this; // return function itself!
};
var myFn = new myFunction();
myFn.public1 // 0
myFn.secret1 // undefined
myFn.addSecrets();
I recommend you to read the excellent Learning JavaScript Design Patterns by Addy Osmani.
What I understand from your explanation as per your second snippet is that you need a sharedPrivate among the instantiated objects. You can not do this with classical object creation patterns like constructor, factory or module. This is possible by taking a private variable under closure in the prototype of the constructor so that it doesn't get reset each time an object is created and at the meantime the instantiated objects are provided with necessary methods to access, modify and share it privately.
function SharedPrivate(){
var secret = 0;
this.constructor.prototype.getSecret = function(){return secret}
this.constructor.prototype.setSecret = function(v){ secret = v;}
this.constructor.prototype.incrementSecret = function(){secret++}
}
var o1 = new SharedPrivate();
var o2 = new SharedPrivate();
console.log(o1.getSecret()); // 0
console.log(o2.getSecret()); // 0
o1.setSecret(7);
console.log(o1.getSecret()); // 7
console.log(o2.getSecret()); // 7
o2.incrementSecret()
console.log(o1.getSecret()); // 8
And another method of getting a similar result would be
function SharedPrivate(){
var secret = 0;
return {getS : function(){return secret},
setS : function(v){secret = v},
incS : function(){secret++}
};
}
sharedProto = SharedPrivate(); // secret is now under closure to be shared
var o1 = Object.create(sharedProto); // sharedProto becomes o1.__proto__
var o2 = Object.create(sharedProto); // sharedProto becomes o2.__proto__
o1.setS(7); // o1 sets secret to 7
console.log(o2.getS()); // when o2 access it secret is still 7
o2.incS(); // o2 increments the secret
console.log(o1.getS()); // o1 can access the incremented value

A Javascript function which creates an object which calls the function itself

I am trying to make an angular service that returns a new object.
That's fine and good and works. new MakeRoll() creates an instance. But self.add, near the end also calls new MakeRoll() and that doesn't create an instance when I call add like I think it should.
I'm probably doing this all wrong but I haven't been able to figure it out.
var services = angular.module('services', []);
services.factory('Roll', [function() {
var MakeRoll = function () {
var self = {};
self.rolls = [];
self.add = function(number, sizeOfDice, add) {
var newRoll = {};
newRoll.number = number || 1;
newRoll.sizeOfDice = sizeOfDice || 6;
newRoll.add = add || 0;
newRoll.rollDice = function() {
var result = 0;
var results=[];
for (var i = 0; i < newRoll.number; i++) {
var roll = Math.floor(Math.random() * newRoll.sizeOfDice) + 1;
result += roll;
results.push(roll);
}
newRoll.results = results;
newRoll.result = result;
newRoll.Roll = new MakeRoll();
};
self.rolls.push(newRoll);
return self;
};
self.remove = function(index) {
self.rolls.splice(index, 1);
};
self.get = function(index) {
return self.rolls[index];
};
return self;
};
return new MakeRoll();
}
]);
angular service is designed to be singleton to accomplish some business logic, so don't mix up plain model with angular service. if you want to have more objects, just create a constructor and link it in service to be operated on.
function MakeRoll() {
...
}
angular.module('service', []).factory('Roll', function () {
var rolls = [];
return {
add: add,
remove: remove,
get: get
}
function add() {
// var o = new MakrRoll();
// rolls.push(o);
}
function remove(o) {
// remove o from rolls
}
function get(o) {
// get o from rolls
}
});

Pass reference of main object to another object

I created this simplified version of some code I'm dealing with. I need to figure out how to pass a reference of an instantiated object to another object that has been created by this object. I can't get the reference to the main object "self" to be passed to the second object and actually be able to call a function on it. Hopefully the code will make it more clear:
var app = app || {};
(function (m, $, undefined) {
m.Counter = function () {
var self = this;
var pub = {};
pub.total = 0;
pub.add = function () {
pub.total++;
};
pub.subtract = function () {
pub.total--;
};
pub.status = function () {
console.log(pub.total);
};
pub.spawn = function () {
var sp = new app.modules.Obj(self);
return sp;
};
return pub;
};
m.Obj = function (counter) {
var pub = {};
pub.add = function () {
counter.add();
};
return pub;
};
}(app.modules = app.modules || {}));
var c = new app.modules.Counter();
c.add();
c.add();
c.add();
c.status();
d = c.spawn();
d.add();
c.status();
What I would want to have happen is that d.add() would increment the total of c. So the output would be 3 for the first c.status() call and then 4 for the output of the second c.status();

scope of returned object in javascript function

How do I access 'a' below?
var test = function () {
return {
'a' : 1,
'b' : this.a + 1 //doesn't work
};
};
You can't do it this way. When you are in the process of constructing an object (that's what you actually do using the curly braces), there is no way to access it's properties before it is constructed.
var test = function () {
var o = {};
o['a'] = 1;
o['b'] = o['a'] + 1;
return o;
};
var t = function ()
{
return new x();
};
var x = function ()
{
this.a = 1;
this.b = this.a + 1; //works
}
abstract a layer
edited for formatting, and noting that this is shifting from OLN
You can't Object Literal Notion does not support this access
var test = function () {
//private members
var a = 1;
var b = a + 1;
//public interface
return {
geta : function () {
return a;
},
getb : function () {
return b;
}
}
}();

Categories

Resources