Best way to combine the module pattern with closures - javascript

I'm currently trying to implement some common JS concepts
in little projects to understand better how to use them.
I've been working on a simple game, trying to
understand and use the module pattern and closures.
I'm using the module pattern from Stoyan Stefanov's 'patterns'
book.
I'm struggling to understand how best to mix modules and
closures.
I'd like to know if I'm organising the following code in a
sensible way? If so, my question is: what's the best way
to modify the code so that in the $(function(){}) I have
access to the update() function?
MYAPP.utilities = (function() {
return {
fn1: function(lives) {
//do stuff
}
}
})();
MYAPP.game = (function() {
//dependencies
utils = MYAPP.utilities
return {
startGame: function() {
//initialisation code
//game state, stored in closure
var lives = 3;
var victoryPoints = 0;
function update(){
utils.fn1(lives);
//do other stuff
}
}
}
})();
$(function(){
MYAPP.game.startGame();
//Want to do this, but it won't work
//because I don't have access to update
$('#button').on('click',MYAPP.game.update)
});
I've come up with a couple of options which would work, but
I'd like to know if they're good practice, and what the best
option is.
Options:
(1) Bind $('#button').on('click', ...) as part of the
startGame initialisation code.
(2) Assign the update() function to a variable, and
return this variable from the startGame function, So in
$(function(){}) we could have
updatefn = MYAPP.game.startGame(); and then
$('#button').on('click',MYAPP.game.update)
(3)? Is there a better way?
Thank you very much for any help,
Robin

First off, to access the update function in that fashion it will have to exposed in the returned object.
return {
update: function() {
[...]
},
startGame: function() {
[...]
this.update();
}
}
Calling obj.method() automatically sets the this reference inside this method call to obj. That is, calling MYAPP.game.startGame() sets this to MYAPP.game inside this startGame method call. More details about this behavior here.
You will also want to move the lives variable to a common scope which is accessible by both startGame and update methods, which is exactly what the closure is for:
MYAPP.game = (function() {
[...]
var lives; //private/privileged var inside the closure, only accessible by
//the returned object's function properties
return {
update: function() {
utils.fn1(lives);
},
startGame: function() {
[...]
lives = 3; //sets the closure scope's lives variable
[...]
this.update();
}
}
})();
Fiddle
In this case you will need some method to set the lives variable when you want to change it. Another way would be to make the lives variable public as well by making it a property of the returned object and accessing it through this.lives inside of the methods.
NOTE: If you simply pass a reference to the function object stored as property of the returned object as in:
$('#button').on('click', MYAPP.game.update);
The this reference inside the click handler will not point to MYAPP.game as the function reference that has been passed will be called directly from the jQuery core instead of as an object's member function call - in this case, this would point to the #button element as jQuery event handlers set the this reference to the element that triggered the handler, as you can see here.
To remedy that you can use Function.bind():
$('#button').on('click', MYAPP.game.update.bind(MYAPP.game));
Or the old function wrapper trick:
$('#button').on('click', function() {
MYAPP.game.update(); //called as method of an obj, sets `this` to MYAPP.game
});
This is important when the this keyword is used inside the update method.

There are a few issues in your code. First, update() function is not visible outside the object your creating on the fly. To make it part of game object it has to be on the same level as startGame.
Also, if you declare var lives = 3 it will be a local variable and it won't be visible outside startGame() function, as well as victoryPoints. These two variable have to be visible in some way (via closure or as object fields).
Finally, attaching MYAPP.game.update as an event listener will attach just that function, preventing you from using all other object methods/functions. Depending on what you want to do you might prefer to pass a closure like function() { MYAPP.game.update() } instead.
Your code should look something like:
MYAPP.utilities = (function() {
return {
fn1: function(lives) {
console.log(lives);
}
}
})();
MYAPP.game = (function() {
//dependencies
utils = MYAPP.utilities
var lives;
var victoryPoints;
return {
startGame: function() {
//initialisation code
//game state, stored in closure
lives = 3;
victoryPoints = 0;
},
update: function() {
utils.fn1(lives);
//do other stuff
}
}
})();
$(function(){
MYAPP.game.startGame();
//Want to do this, but it won't work
//because I don't have access to update
$('#button').on('click', MYAPP.game.update)
});
(DEMO on jsfiddle)

Related

What is the correct way of calling an internal function using the module pattern in Javascript

I am new to Javascript and am still getting my head round the various ways of creating objects i.e constructor+new, prototypal, functional & parts.
I have created what I think is an object factory using the module pattern and want to know what the correct method of calling an internal method would be. Is it via this or function name.
Here is my module:
function chart() {
function my() {
// generate chart here, using `width` and `height`
}
my.sayHi = function(){
console.log('hi');
my.sayBye();
};
my.sayBye = function(){
console.log('Bye');
};
return my;
}
var test = chart();
test.sayHi();
You can see that the first function calls the second using my.sayBye() or is it better to use this.sayBye(). Both produce the same result and run without error.
The module pattern allows you to dispense with the 'this' variable if you want to. I would probably rewrite the above code to look like this and then the question becomes moot.
function chart() {
var hiCount = 0;
function sayHi(){
console.log('hi');
hiCount++;
sayBye();
};
function sayBye(){
console.log('Bye');
};
return {
sayHi : sayHi,
sayBye: sayBye
};
}
var test = chart();
test.sayHi();
In the above code all is defined within the function chart. As JavaScript's scope is at the function level every time the chart function is called a new set of functions will be defined. And a new set of variables can also be defined that are private to the function as they are defined in the function and are not accessible from outside. I added hiCount as an example of how you could do this. The Module pattern allows privacy in JavaScript. It eats more memory than the prototype pattern though as each time a function is declared it is not shared between other instances of the same class. That is the price you have to pay in Javascript to have class variables that are private. I willingly pay it. Removing 'this' from my code makes it easier to understand and less likely that I will fall into problems of misplaced scope.
Using "this" is better approach because you would be able to bind the function directly to the parent function object.And you dont need to return anything from the function.
where as in your case you are explicitly returning another function
Here is the use of "this" approach
function chart() {
this.sayHi = function(){
console.log('hi');
}
}
var test = new chart();
test.sayHi();
Using this approach you would be able to call anything in the prototype of function "chart"
Eg
chart.prototype.hello = function(){
console.log('hello')
}
So you would be able to call the hello function from the same object(test)

Access to public and private methods from event handler closure

I have a difficulty in understanding, how my current JavaScript code works. I've managed to solve a problem in accessing private object method from event handler closure, but I'd like to know why does it work so.
The code utilizes the well-known module/plugin metaphor:
(function(module, $, undefined)
{
function myPrivateCode(e){ /*...*/ }
module.myPublicCode = function(e) { /*...*/ }
module.init = function()
{
var that = this;
$('.clickable').click(function(e)
{
if($(e.target).hasClass('classX'))
{
that.myPublicCode(e.target); // requires 'that' to work
}
else
{
// that.
myPrivateCode(e.target); // will fail if 'that' uncommented
}
});
}
}(window.module = window.module || {}, jQuery ));
In the code I set a click handler which invokes either public or private method. It's perfectly conceivable that we need to pass an object reference into the event handler closure, which is done by that local variable. What is strange to me is that myPrivateCode does neither require that as a refernce, nor fails due to its "privacy". This makes me think that myPrivateCode accesses not the appropriate object, and works somehow differently to expected way. Could someone explain what happens? Certainly I'm missing something.
Both that and myPrivateCode are available to your event handler through a closure. In short, what's going on is that every variable and function you declare inside of another function has access to the outer scope.
myPublicCode, on the other hand, is not available through closures, because it's being assigned to your module object specifically. So the only way to call it is by using module.myPublicCode() (or that.myPublicCode() as you did – but you don't actually need that there, since module is also available).
Your call to myPrivateCode(e.target); is running in the context of the anonymous function that you pass as a handler to the click function.
For more information, read up on closures.
For a simpler example, try out this code:
var foo = function () {
var a = 1;
return function (b) {
return a+b;
}
};
var bar = foo();
bar(1); // 2
bar(1) will always always gives 2, because a = 1 was in scope when the function was created. In your case, a is your that and your handler is the closed function.
http://jsfiddle.net/Fh8d3/

Can someone explain the following piece of Javascript code?

I was reading another question, and I saw this:
var basketModule = (function() {
var basket = []; //private
return { //exposed to public
addItem: function(values) {
basket.push(values);
},
getItemCount: function() {
return basket.length;
},
getTotal: function(){
var q = this.getItemCount(),p=0;
while(q--){
p+= basket[q].price;
}
return p;
}
}
}());
Can you please explain why does he wrap the function in ( and )'s? Also, what is the purpose of that return? Couldn't he just write self.addItem = ... and so on?
When you wrap a function with parantheses, and add () to the end of it, it's a self executing function.
(function() x() {
//do something;
})();
And, by returning he's making basket variable somewhat private. Try getting basketModule.basket from anywhere else, and you'll get undefined.
That is called javascript Module Pattern. Defining a function and calling it immediately to prevent variables to be in the global space or to define a function name.
Note parentheses in the last line: (). The function is defined and immediately called:
(function() { })();
return { ... } returns an object having a method addItem
The intention of the code is to create an object with three methods. addItem,getItemCount and getTotal. They all depend on state represented by basket.
if basket was defined globally that state would be exposed (and there could only ever be one variable basket. both of those can lead to issues so by wrapping the entire declaration the state is encapsulated and only accessible from the created object.
There are other ways of achieving the same and the pro's and con's are related to style and how many objects of that particular type you're going to need.
wrapping the function(){}() is required since function(){}() will not parse

javascript anonymous function parameter passing

I have some javascript code (within an object) :
toggle: function() {
var me = this;
var handler = function() { me.progress() };
me.intervalId = setInterval(handler, me.intervalTime);
//...More code
}
I'm kind of new to javascript, so doing the above as far as I can tell actually passes the me variable into anonymous the function. I was wanting to see if there is a more declarative way to do so? I wanted something along the line of:
var handler = (function(o) { o.progress();})(this));
but that doesn't seem to be working... Am I missing something? Is this a case where "this is the way the language works so just declare a local variable and deal with it"?
UPDATE:
The source to my problem was/is my unclear understanding of scope and closures in javascript. I found this article to help me understand a little more.
You can use ".bind()":
var handler = function() { this.progress(); }.bind(this);
New browsers have "bind()", and the Mozilla docs have a solid implementation you can use to patch older browsers.
The reason
var handler = (function(o) { o.progress();})(this));
doesn't work because it just immediately calls the anon function, therefore immediately calling o.progress() and assigns the return value of the anon function (undefined) to handler. You need to return an actual function from the outer function:
handler = (function(me){
return function(){
return me.progress();
}
}(this));
On the flip side this is equivalent and just as bad looking as bad looking as the variable assignment (but can still be useful, particularly if this needs to be done in a loop, with the changing i rather than the fixed this).
BTW, if the progress function doesn't have any calls to this inside it , just doing handler = this.progress (without the parens) might suffice.
The anonymous function has access to me because it is declared inside of the outer function (the toggle function); it is closed over by the outer function.
Your handler function will be called by setInterval, which passes exactly zero arguments. This means you can't use parameters in the handler function itself.
I you really want to pass me explicitly, you could write a function accepting an parameter, and have that function return an anonymous function without parameters, but which could access the creator function's parameter:
toggle: function() {
var me = this;
var handler = (function (o) { return function() { o.progress() }; })(me);
me.intervalId = setInterval(handler, me.intervalTime);
//...More code
}
But this basically adds a layer of redirection without really making it more legible. Unless you pull that creating function outside:
function createProgressHandler(o) {
return function() {
o.progress();
};
}
// ...
toggle: function() {
var me = this;
var handler = createProgressHandler(me);
me.intervalId = setInterval(handler, me.intervalTime);
//...More code
}
What you have there is a closure. The function that is created and assigned to handler keeps a reference to the me object. This is normal, everyday JavaScript, and that's the way that closures work generally.
Have you tried to return the function like this?
var handler = function(o){
return function(){
o.progress();
}
}(me);
Now you can call:
handler();

How can I safely access other sibling functions and variables in a Javascript Module Pattern without accessing something in the containing scope?

I have a Javascript Object structured after the Module Pattern. I have several private function in it which are called from other sibling "private" functions. How can I access another variable/function without the potential to accidentally access a global/external variable/object/function?
function doSomething() {
alert("Something I don't want to do");
}
var My.Namespaced.SingletonClass = (function() {
var init = function() {
doSomething();
}
var doSomething = function() {
alert("Something I want to do");
}
return {
"init": init;
}
})();
My.Namespaced.SingletonClass.init();
My guess is that the above code would in fact access the correct, inner doSomething function, but I'd like some more security than that. How can I explicitly address the inner/nested function without fear of accidentally calling functions or addressing objects in the scope around my singleton?
Short version: you can't. If doSomething isn't defined as a sibling of init, then JavaScript will search successively broader scopes until it finds a doSomething function, or it runs out of scopes to search.
Longer version: you can prevent this sort of behavior by using a private object to hold your private helper functions, like this:
function doSomething() {
alert("Something I don't want to do");
}
// Assuming My.Namespaced is already defined:
My.Namespaced.SingletonClass = (function() {
var helpers = {};
helpers.doSomething = function() {
alert("Something I want to do");
}
var init = function() {
helpers.doSomething();
}
return {
init: init
}
})();
My.Namespaced.SingletonClass.init();
I'm not sure if it's important that the helper functions are truly siblings (but I don't see why that would particularly matter).
Also keep in mind that My and My.Namespaced need to be defined before you tack on SingletonClass - and there's no need to use JSON-style quoting for keys in the object you're returning.

Categories

Resources