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.
Everytime you nest a function, you have to think about this
. But if you dont nest a function, or that function doesn't use this
you don't need to think about it.
init: function () {
var self = this;
self.getAjaxVar();
},
So in this case it's not necessary. This is exactly the same:
init: function () {
this.getAjaxVar();
},
But here:
getAjaxVar: function() {
var self = this;
$.get('ajax/test.html', function(response) {
self.someVarToBeSetUsingAjax = response.value;
});
},
You create an inner function, and you want a reference to the original value of this
, so you do have to alias this
to self
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.
var func = function() { return this.name };
var obj = { name: 'Bob' };
var boundFunc = func.bind(obj);
boundFunc(); // 'Bob'
bind
will return a new function with this
always set to a specific object.
So:
getAjaxVar: function() {
$.get('ajax/test.html', function(response) {
this.someVarToBeSetUsingAjax = response.value;
}.bind(this));
},
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.
obj = {
name: "bob"
sayHello: ->
doSomeAjax({
success: =>
alert "successfully made " + this.name + " say hello!"
})
}
obj.sayHello()
->
makes a normal function. But the fat arrow =>
will instead preserve the value of this
inside and outside the function. It's very very handy in callbacks within instance methods. When compiled to JS, it basically does a self = this
alias for you, using self
within the inner function everytime to reference this
. It's pretty slick.
In plain JS though, the most common pattern is simply self = this
, stick to it.