I'll use the following JavaScript code to demonstrate what I am trying to do.
var App = function() {
var url
var width
var height
function init()
{
url = window.location.href
width = document.body.clientWidth
height = document.body.clientHeight
}
function run()
{
init()
alert(url + ' - ' + width + 'x' + height)
}
return {
run: run
}
}()
App.run()
( Run this code at: http://jsfiddle.net/zePq9/ )
The above code achieves three things:
App
which is intentionally exposed to the global namespace).url
, width
and height
variables and the init()
function within the anonmyous function.run()
function outside the anonymous function.However, I do not like this approach much because the init()
and run()
functions have to work with variables like url
, width
and height
. In a more involved and larger JavaScript code, it is difficult to see the variable url
in a function and tell where it is coming from. One has to do a lot of scrolling to answer questions like: Is it a local variable? Is it a global variable? Is it local only to the anonmyous function?
Right now I am solving this problem with the following code.
var App = function() {
var self = {
url: '',
width: 0,
height: 0
}
function init()
{
self.url = window.location.href
self.width = document.body.clientWidth
self.height = document.body.clientHeight
}
function run()
{
init()
alert(self.url + ' - ' + self.width + 'x' + self.height)
}
return {
run: run
}
}()
App.run()
( Run this code at: http://jsfiddle.net/cXALf/ )
Now, I can clearly see self.url
and tell that this variable is coming from the self
object, the scope of which I know is limited to the anonmyous function due to my coding convention of using self
object to hold together variables shared by all functions within an anonymous function. Note that self.url
is still hidden within the anonymous function and is not visible outside it.
Ideally, I would like to use this.url
, this.width
, etc. instead of self.url
, self.width
, etc. But I am unable to arrive at a solution that would keep this.url
, this.width
, etc. invisible from outside the anonmyous function. Is it possible?
You can use bind
to permanently set the this
value of each function:
var App = function() {
var self = {
url: '',
width: 0,
height: 0
};
var init = function()
{
this.url = window.location.href;
this.width = document.body.clientWidth;
this.height = document.body.clientHeight;
}.bind(self);
var run = function()
{
init();
alert(self.url + ' - ' + self.width + 'x' + self.height);
}.bind(self);
return {
run: run
}
}();
Note the older browser don't support bind, but you can use a polyfill to add it to browsers that don't supply it automatically.
Note that I don't necessarily think this code is a good idea, but it does do exactly what you want. I personally think there's nothing wrong with using self
as an explicit container for your variables, and using this
instead may make your code harder for others to understand (as they may assume App
is meant to have instances).