views:

307

answers:

1

Say I got this singleton object with some public methods and one private method:

var QuestionFactory = (function() {

// private method
function google_it_first() { ... }

// public methods
return {
  ask_a_stupid_question:                function() { ... },
  ask_a_relatively_non_stupid_question: function() { ... },
  ask_a_difficult_question:             function() { ... }
}  

})();

What I'd like to be able to do is call google_it_first method first, when any public method is called. How do I implement it without explicitly calling it inside each public method?

+2  A: 
function wrapper() {
  return function() {
    google_it_first();
    return arguments[0](arguments.slice(1,arguments.length);
  }
}

ask_a_stupid_question: wrapper(function() { ... })

Of the top of my head, I think that would work.

Ben Hughes
+1 That was my first thought also, just note that `arguments` unfortunately is not a *real array* object, you need to invoke the `slice` method on the `Array.prototype` object using `call`. E.g: `var args = Array.prototype.slice.call(arguments, 1);`, also, you might want to use `apply` to invoke the wrapped function and send the arguments separately, e.g. `arguments[0].apply(null, args);`
CMS
Maybe I didn't understand it, but it seems that I'd have to use wrapper function on each of the methods. Which is, in terms of code duplication, is identical to calling google_it_first() inside each of those methods. What's the point then?
snitko
Yes, you would have to do that. The thing is you can then add as many functions to the wrapper without having to change it for all the methods. I would debate that the mechanism is quite different in terms of duplication as it still separates aspects/concerns. The point is that that is how javascript works. Before_filters in rails are implemented in the request system rather than at the method level anyway.
Ben Hughes
Yes, you'd have to apply the wrapper function to each method, but you can do that by saying `for (method in methods) rv[method] = wrap(methods[method]);`. That is, in terms of code duplication, not at all identical to calling `google_it_first()` inside of each method.
Kragen Javier Sitaker