PDA

View Full Version : Static functions and scope



hvtilborg
10 Jan 2012, 1:48 AM
Hey guys,

I have the following class:


Ext.define('DC.misc.Cockpit', {

singleton: true,

doXHRIfConfirmed: function(config)
{
config = Ext.apply({
route: 'pingpong',
title: '',
question: 'Sure?',
params: null,
successMsg: 'Successful.',
successFn: function() {},
failureMsg: 'Failure.',
failureFn: function() {}
}, config || {});

Ext.Msg.confirm(
config.title,
config.question,
function(button)
{
if (button == 'yes') {
Ext.Ajax.request({
method: 'POST',
url: Routing.generate(config.route),
params: config.params,
success: function(response)
{
var json = Ext.decode(response.responseText);
if (json.success) {
DC.misc.Cockpit.showInfoMsg(config.title, config.successMsg);
config.successFn();
} else {
DC.misc.Cockpit.showErrorMsg(config.failureMsg);
config.failureFn();
}
},
failure: function()
{
DC.misc.Cockpit.showErrorMsg(config.failureMsg);
config.failureFn();
},
scope: this
});
}
},
this
);
}

Now I'd like to call this static function like this:


DC.misc.Cockpit.doXHRIfConfirmed({
route: 'client_json_destroy',
params: {
client_id: this.clientId
},
title: 'Deactivate client',
successFn: function() { me.doReload(); },
scope: this
});

But of course, the scope is wrong then (i.e. 'scope: this' has no effect). Should I call DC.misc.Cockpit.doXHRIfConfirmed() using Ext.callback or Ext.Function.bind, or...?

Dipish
10 Jan 2012, 2:18 AM
To call functions with custom scope, use JavaScript's native Function.call (https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/call) or Function.apply (https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply).

For example:
DC.misc.Cockpit.doXHRIfConfirmed.call({/* your config */}, this);

Your question actually has nothing to do with ExtJS but you can use Ext.callback (http://docs.sencha.com/ext-js/4-0/#!/api/Ext-method-callback) if you don't want to use pure JavaScript:
Ext.callback(DC.misc.Cockpit.doXHRIfConfirmed, this, [{/* your config*/}]);
Note the square brackets as Ext.callback accepts an Array of arguments.

Ext.bind (http://docs.sencha.com/ext-js/4-0/#!/api/Ext.Function-method-bind) creates a new function that calls your original function with modified scope and/or arguments. The usecase for it is the following:
var doXHR = Ext.bind(DC.misc.Cockpit.doXHRIfConfirmed, this, [{/* your config*/}]);
// later in the code:
doXHR();
// or like that:
myButton.on('click', doXHR);

hvtilborg
10 Jan 2012, 2:25 AM
Thanks Dipish. I wonder whether you would consider this design (using the static method) good practice, or are there nicer ways to achieve this?

Dipish
10 Jan 2012, 2:33 AM
But why do you want to call a method of your class with a custom scope?

hvtilborg
10 Jan 2012, 2:35 AM
Because I wanted to have access to the object that calls doXHRIfConfirmed(). As you can see in the successFn() function.

I'm avoiding that now using the 'me' (which is 'var me = this') instead of 'this.doReload()'.

Dipish
10 Jan 2012, 2:41 AM
Sorry, I didn't read your code attentively. Replace

config.successFn();
with

config.successFn.call(config.scope);
To solve your troubles.

hvtilborg
10 Jan 2012, 2:44 AM
Great, thanks for your help!

Scope is getting more and more clear :].