I have inherited a code base that I need to update for my job. I'm slowly learning what they are trying to acplish with the closure that is in place, but I am getting stuck when trying to update a part of the site that uses this functionality. I'll give a basic outline of what the code is trying to acplish and see if anyone can help.
var TheObject = (function (){
var veryLargeDependantData = {
var1: {},
var2: {},
var3: [],
//Set these variables via functions
function1: function f1(data){...},
function2: function f2(data){...},
initialize: function initialize() { //set values for var1... var3}
};
return {initialize: veryLargeDependentData.initialize};
})().initialize();
Since I obviously cannot show production code on the site this will have to do. But basically the veryLargeDependentData variable is the entrance to the function. When the page loads it calls the initialize function and everything is happy. But now I need to add this to an onclick event for and older page and the firebug console says that the variable is undefined. In the other pages I am able to use it with no problem.
My question is what magic is going on that causes the closure not to be part of a callable namespace such as this. I'm a bit of a javascript nOOb so I apologize if the question sounds misguided.
onclick='TheObject.initialize();'
I have inherited a code base that I need to update for my job. I'm slowly learning what they are trying to acplish with the closure that is in place, but I am getting stuck when trying to update a part of the site that uses this functionality. I'll give a basic outline of what the code is trying to acplish and see if anyone can help.
var TheObject = (function (){
var veryLargeDependantData = {
var1: {},
var2: {},
var3: [],
//Set these variables via functions
function1: function f1(data){...},
function2: function f2(data){...},
initialize: function initialize() { //set values for var1... var3}
};
return {initialize: veryLargeDependentData.initialize};
})().initialize();
Since I obviously cannot show production code on the site this will have to do. But basically the veryLargeDependentData variable is the entrance to the function. When the page loads it calls the initialize function and everything is happy. But now I need to add this to an onclick event for and older page and the firebug console says that the variable is undefined. In the other pages I am able to use it with no problem.
My question is what magic is going on that causes the closure not to be part of a callable namespace such as this. I'm a bit of a javascript nOOb so I apologize if the question sounds misguided.
onclick='TheObject.initialize();'
Share
Improve this question
edited May 31, 2013 at 16:41
jerry
2,6111 gold badge23 silver badges32 bronze badges
asked May 31, 2013 at 14:42
Michael GuantonioMichael Guantonio
4091 gold badge6 silver badges14 bronze badges
7
-
Can you show us the code from the
onclick
event? – crush Commented May 31, 2013 at 14:45 -
verylargeDependentData()
doesnt exist at the global scope, thus you can't call it in that manner. Only way it get's called is throughTheObject.initialize()
currently. (hard to tell due to the typos) – crush Commented May 31, 2013 at 14:48 -
1
verylargeDependentData
is not a function (in addition to being out of scope), what are you actually trying to do with it? Initialize it when the button is pressed instead of when the page loads? – jerry Commented May 31, 2013 at 14:49 - @jerry that is exactly what I am trying to do. I want to load it as the page loads, but also on the onclick event. This is inherited code btw, so it is possible its less than pristine. – Michael Guantonio Commented May 31, 2013 at 14:51
- I'm still not sure what that return statement is doing there. – crush Commented May 31, 2013 at 14:51
3 Answers
Reset to default 5I assume what you mean is that you want to run the initialize
function in a click event handler, and you're currently attempting to do so like this:
TheObject.initialize();
If that's the case, the problem is that TheObject
actually refers to the return value of initialize
, since you called initialize
on the return value of the immediately-invoked function expression. And the chances are that initialize
is returning undefined
(most likely, it has no explicit return
statement).
To solve this, you probably want to remove the immediate call to initalize
, which will allow you to use the line shown above both on page load and anywhere else.
In this code, the value of TheObject
will be whatever the veryLargeDependentData.initialize()
method returns. If the initialize method returns nothing, TheObject
will be undefined.
A simplified example:
var TheObject = (function () {
return {
initialize: function () {
// stuff happens here, but importantly, there's nothing returned
}
}
})().initialize();
You can break this down into the following order of execution:
// the value of step_one is a function that will return an object when it is run
var step_one = (function () {
return {
initialize: function () {
// ...
}
}
});
// after running the function step_one, step_two will be an object
// containing one key - initialize - which is a function
var step_two = step_one();
// since initialize doesn't return anything, TheObject is set to undefined.
var TheObject = step_two.initialize();
You can get around this by setting TheObject
to be the object containing the initialize method then run that method again whenever you need it.
var TheObject = (function () {
return {
initialize: function () {
}
}
})();
// initialize
TheObject.initialize();
// and again
TheObject.initialize();
PLEASE NOTE!
The original author may have intended for the initialize method to only be run once. Running it more than once might introduce bugs into your system!
Seems unnecessarily plicated, I'm not sure what is gained by using the anonymous function and closure in this case. Is there any reason you can't simple do the following?
var TheObject = {
var1: {},
var2: {},
var3: [],
//Set these variables via functions
function1: function(data){...},
function2: function(data){...},
initialize: function(){alert("initialize");}
};
var initButton = document.getElementById("initButtonName");
initButton.addEventListener("click", TheObject.initialize);
Note that you'd want to remove the inline event.