I've been reading for hours and can't seem to find an answer that suits my needs. I don't want to change up the structure at this point, due to the size of the code. I am trying to find a solution that works from within the structure I've already got in place, if at all possible.
First, here is a very simplified mock-up of my object literal structure:
NS =
{
x: undefined,
button: undefined,
fn:
{
root: undefined,
doSomething: function ()
{
var root = this.root,
x = root.x; // exception occurs here
// do something with x
}
},
init: function ()
{
var self = this,
x = self.x,
button = self.button,
fn = self.fn,
fn.root = self;
x = $("#x");
button = $("#button");
button.on("click", fn.doSomething);
}
};
I know it looks like the declarations under init()
aren't really needed, but the namespaces can get rather long, so I like to shorten them like that. This has worked great for me in almost every scenario until I hit this snag. I know I could fully qualify everything and it should work, but I really don't want to do that due to the aforementioned long namespaces.
My issue is that my root property x
doesn't keep its value after it was set in the init()
function when it's being accessed from within another property's function. You can console.log(this.x)
from within the init()
function and it's there. However, when you click the button and the onClick function tries to declare x = root.x
it throws:
Uncaught TypeError: Cannot read property 'x' of undefined
UPDATE:
Adding console.log()
shows that fn.root.x
is undefined even before the handler is called:
init: function ()
{
var self = this,
x = self.x,
button = self.button,
fn = self.fn,
fn.root = self;
x = $("#x");
console.log(x); // this shows the object
console.log(fn.root.x); // this throws the undefined exception
button = $("#button");
button.on("click", fn.doSomething);
}
When doSomething is called as an event handler, this
will be the event target inside the function. So this.root
will be undefined, and undefined doesn't have any properties, so root.x
raises an error.
One solution is to fix the value of this
with $.proxy
:
button.on("click", $.proxy(fn.doSomething, self));