Basically, I use a meta-class framework called Joose for Javascript that allows me to make use of a more elegant class syntax - but I don't know how I might go about referencing the scope of the object from within deeper methods of the class declaration. I also use require.js for dependemcy management...
Here's an example class definition:
define([
'jquery',
'handlebars',
], function($, Handlebars){
var MyClass = Class("MyClass", {
//inheritance
isa: SuperClass,
//instance vars
has: {
hello:{
is: 'r',
init: 'Hi There!',
},
someVarToBeSetUsingAjax:{
is: 'rw',
init: false,
},
},
//methods
methods: {
init: function () {
var self = this;
self.getAjaxVar();
},
getAjaxVar: function() {
var self = this;
//HOW CAN I REFERENCE 'self' THROUGHOUT MY OBJECT?
$.get('ajax/test.html', function(response) {
self.someVarToBeSetUsingAjax = response.value;
});
},
//lots more methods...
}
});
return MyClass;
});
Ok, so my issue is - in the AJAX function I have to write var self = this to get my object into the scope of the AJAX call - no problem. But, I find myself doing this for almost every single method in my class declaration! How can I reference self in all of the methods in a clean and efficient way? I know you can use scope in AJAX by setting a parameter, assume it's not just AJAX but other functions that close the scope to the outside.
Thanks.
You cannot. The value of
self
, the instance referenced bythis
, is only known on calling the method.You only could work around that and use one common
self
variable if you declared that in the constructor (yourinit
method?) and created all the callback functions there as well. Might not be the most memory-efficient method, though:Everytime you nest a function, you have to think about
this
. But if you dont nest a function, or that function doesn't usethis
you don't need to think about it.So in this case it's not necessary. This is exactly the same:
But here:
You create an inner function, and you want a reference to the original value of
this
, so you do have to aliasthis
toself
to make it accessible.There isn't a way to fix
this
to a value from everywhere in your class.That said, you do have some options.
Function.prototype.bind()
can help.bind
will return a new function withthis
always set to a specific object.So:
Note this isn't supported in all browsers, you may need a shim for the old ones.
Or just get used to
self = this
.I want to give a minor nod to coffeescript as well, because it supports declaration of functions that dont change the context when run.
->
makes a normal function. But the fat arrow=>
will instead preserve the value ofthis
inside and outside the function. It's very very handy in callbacks within instance methods. When compiled to JS, it basically does aself = this
alias for you, usingself
within the inner function everytime to referencethis
. It's pretty slick.In plain JS though, the most common pattern is simply
self = this
, stick to it.The answer is to use
this
. You only need to create a closure (which you do with thevar self = this;
when you have a function which will be called external to the object. (as you do here with the return from the ajax call).There is no other way to create a closure.
To be clear (since some will jump on any slight technical hand waving), you don't "need" to create a closure. But I think you should -- JavaScript was designed to work with closures, they work well and they are well understood by other JavaScript programmers.
Apart from always keeping all instances of MyClass in scope (or as a global variable), I don't see any solutions. However, you could do away with having to declare
self
everywhere by usingFunction.prototype.bind
:This isn't limited to $.get(), you can use it everywhere you're using callback functions.