17

Forgive my ignorance as I am not as familiar with jquery. Is there an equivalent to dojo.hitch()? It returns a function that is guaranteed to be executed in the given scope.

-- edit -- As requested, here is an example. I use hitch very frequently to ensure callbacks are executed within the right object. For example, let's say I have a utility method called doSomethingAsync and I pass it a callback function. With hitch, I can make sure the function is executed within a particular scope even if the utility method performs ajax calls and so forth:


expectedScopeObj = {
   flag: true,
   callback: function(){console.debug(this.flag);},
   main: function() {
     // without hitch the callback function would not find flag  
     core.util.doSomethingAsync(dojo.hitch(this, this.callback));
   }
}

Without hitch, the callback function could possibly be executed in a different scope and an error would be thrown with this.flag being undefined. However, with hitch it is guaranteed to be executed within execptedScopeObj.

Lightbeard
  • 4,011
  • 10
  • 49
  • 59

7 Answers7

43

I know this has been answered, but not correctly. jQuery.proxy is what you are looking for I believe.

UPDATE

Many, many years later after lots of JavaScript work, and after stripping out my usage of jQuery since browser compatibility has become less of an issue, I would recommend using Function.prototype.bind over jQuery.proxy, as @bobince suggested. While this is still the correct answer to the original question, I feel obligated to direct people to a vanilla solution rather than relying on jQuery.

LordZardeck
  • 7,953
  • 19
  • 62
  • 119
6

[ADMIN EDIT: Note the much more popular answer, below.—danorton]

I'd go for function.bind, which will be the standard way of doing this in future versions of JavaScript. As well as fixing this , it allows you to pass arguments through to the target functions.

Until all browsers support it natively, you can hack support in yourself.

Community
  • 1
  • 1
bobince
  • 528,062
  • 107
  • 651
  • 834
  • although bind is similar and certainly very useful, it doesn't quite accomplish the task – Lightbeard Jan 13 '10 at 05:53
  • Erm... it accomplishes the task of calling back a function with `this` set appropriately. What else do you expect `hitch` to do? Your example code above doesn't work at all. – bobince Jan 13 '10 at 12:46
  • You're right. I misunderstood and thought you were referring to jquery's bind function. Thanks – Lightbeard Jan 13 '10 at 13:35
2

No. Not in 1.3.2, at least, as I don't know about 1.4. There are, however, some plugins:

(function($) {
  $.fn.hitch = function(ev, fn, scope) {
    return this.bind(ev, function() {
      return fn.apply(scope || this, Array.prototype.slice.call(arguments));
    });
  };
})(jQuery);  
Victor Nicollet
  • 24,361
  • 4
  • 58
  • 89
  • We try if at all possible to avoid using plugins only because we prefer to go with the support of a base library. It looks like right now our best bet is to use a combined dojo base and jquery build so we get the best of both worlds :) – Lightbeard Jan 13 '10 at 05:55
  • This is necromancer territory, but for anyone else who hasn't already solved this, you may wat to look at @phiggins' hitch plugin: https://github.com/phiggins42/bloody-jquery-plugins/blob/master/hitch.js – Oskar Austegard Oct 04 '11 at 21:37
  • Even more zombie-like, I just reposted that link above – PHearst Jul 01 '13 at 22:28
1

The function.bind mentioned by bobince is a pretty useful tool. You could use it to rewrite the hitch function pretty simply:

// The .bind method from Prototype.js 
if (!Function.prototype.bind) { // check if native implementation available
  Function.prototype.bind = function(){ 
    var fn = this, args = Array.prototype.slice.call(arguments),
        object = args.shift(); 
    return function(){ 
      return fn.apply(object, 
        args.concat(Array.prototype.slice.call(arguments))); 
    }; 
  };
}

jQuery.hitch = function(scope, fn) {
  if (typeof fn == "string") fn = scope[fn];
  if (fn && fn.bind) return fn.bind(scope);
};

At least based on the doc page you linked, this is how I saw the function working...

gnarf
  • 105,192
  • 25
  • 127
  • 161
1
//why not just:
(function($){
  $.hitch = function(scope, fn){
    return function(){
      return fn.apply(scope, arguments);
    }
  }
})(JQuery);
//This works exactly like Dojo's hitch from what I can tell.
Leland
  • 11
  • 1
0

In my mind, hitch in Dojo is more complex,

e.g.,

function f(a,b,c){return a+b*c}
var newF = hitch(null,f,1,undefined,3);
newF(2) /*1+2*3*/
Abhijeet Kasurde
  • 3,937
  • 1
  • 24
  • 33
0
/**
 * This is for simulate dojo.hitch.
 * @param $
 */
(function($) {
    $.hitch = function(context, func) {
        var args = Array.prototype.slice.call(arguments, 
                2/*Remove context, and func*/);

        return function() {
            return func.apply(context, 
                    Array.prototype.concat.call(args, arguments));
        };
    };
})(jQuery);
Community
  • 1
  • 1
olojiang
  • 21
  • 5