I’m just getting into using prototypal JavaScript and I’m having trouble figuring out how to preserve a this reference to the main object from inside a prototype function when the scope changes. Let me illustrate what I mean (I’m using jQuery here):
MyClass = function() {
this.element = $('#element');
this.myValue = 'something';
// some more code
}
MyClass.prototype.myfunc = function() {
// at this point, "this" refers to the instance of MyClass
this.element.click(function() {
// at this point, "this" refers to the DOM element
// but what if I want to access the original "this.myValue"?
});
}
new MyClass();
I know that I can preserve a reference to the main object by doing this at the beginning of myfunc:
var myThis = this;
and then using myThis.myValue to access the main object’s property. But what happens when I have a whole bunch of prototype functions on MyClass? Do I have to save the reference to this at the beginning of each one? Seems like there should be a cleaner way. And what about a situation like this:
MyClass = function() {
this.elements $('.elements');
this.myValue = 'something';
this.elements.each(this.doSomething);
}
MyClass.prototype.doSomething = function() {
// operate on the element
}
new MyClass();
In that case, I can’t create a reference to the main object with var myThis = this; because even the original value of this within the context of doSomething is a jQuery object and not a MyClass object.
It’s been suggested to me to use a global variable to hold the reference to the original this, but that seems like a really bad idea to me. I don’t want to pollute the global namespace and that seems like it would prevent me from instantiating two different MyClass objects without them interfering with each other.
Any suggestions? Is there a clean way to do what I’m after? Or is my entire design pattern flawed?
For preserving the context, the
bindmethod is really useful, it’s now part of the recently released ECMAScript 5th Edition Specification, the implementation of this function is simple (only 8 lines long):And you could use it, in your example like this:
Another example:
In this second example we can observe more about the behavior of
bind.It basically generates a new function, that will be the responsible of calling our function, preserving the function context (
thisvalue), that is defined as the first argument ofbind.The rest of the arguments are simply passed to our function.
Note in this example that the function
fx1, is invoked without any object context (obj.method()), just as a simple function call, in this type of invokation, thethiskeyword inside will refer to the Global object, it will alert “global test”.Now, the
fx2is the new function that thebindmethod generated, it will call our function preserving the context and correctly passing the arguments, it will alert “obj test 1, 2, 3, 4, 5” because we invoked it adding the two additionally arguments, it already had binded the first three.