Class mutator Binds.

Original author: Jan Kassens
  • Transfer
In a discussion of a recent topic, the habrasociety became interested in the details of writing classes for MooTools and, in particular, mutators. In this regard, I wanted to write something on this topic, until I came across an article by one of the developers of MooTools. In this topic, I translate an article in which Jan Kassens describes an example of the use of class mutators.

When writing a class, you may need to bind a class method to an event as a handler and use it thisinside it as an instance of the class. You can say that this is not a problem when using bind(). All this is true, but exactly until it comes to removing the event handler, becauseFunction::bind()works so that it returns a new function that wraps the original. Therefore, you need to save the wrapper somewhere in order to remove the handler (without deleting all the event handlers of the element, which is not very good inside the portable class).

Note by the author of the translation . The author of the article means the case when an event handler is assigned using el.addEvent('click', myFn.bind(this)). Therefore, it cannot be deleted with el.removeEvent('click', myFn.bind(this)), because it bind()will return a new function, not the one that was used in addEvent(). The only solution in this case is to remove all element handlers using el.removeEvents('click'), but this will affect all handlers, including those that could be assigned by third-party classes.

What I saw several times is an object containing all the bound functions that is created in the constructor, as can be seen from the example: I did not like this solution because it is too cumbersome: why should I always use it when I use bound functions? And, then, I do not want to bind these functions manually each time. After considering various solutions, I came to one that is optimal in speed (do not be afraid, this is faster than the solution above) and convenience. This is a new, so-called "class mutator . " Many of you may not have heard of class mutators before, but you definitely used them when writing your classes. Built-in mutators: and , and here is the code :
var MyClass = new Class({
  initialize: function(){
   this.bound = {
     sayHello: this.sayHello.bind(this),
     sayGoodbye: this.sayGoodbye.bind(this)
   }
   // Далее используем только this.bound.sayHello и
   // this.bound.sayGoodbye внутри класса
  },

  sayHello: function() { /* ... */ },
  sayGoodbye: function() { /* ... */ }
});

this.bound.myFn

BindsImplementsExtendsBinds
Class.Mutators.Binds = function(self, methods) {
  $splat(methods).each(function(method){
   var fn = self[method];
   self[method] = function(){
     return fn.apply(self, arguments);
   };
  });
};

This mutator overrides all methods passed to it in strings by new versions bound to the instance. Binds: 'foo'just binds footo the class, Binds: ['foo', 'bar']binds fooand bar. Pretty simple, isn't it?

Now let's see how the class will be simplified using the mutator Binds: I hope you figured it out a bit and can find some use for this.
var MyClass = new Class({
  Binds: ['sayHello', 'sayGoodbye'],

  initialize: function(){
   // Теперь используем только this.sayHello и
   // this.sayGoodbye внутри класса
  },

  sayHello: function() { /* ... */ },
  sayGoodbye: function() { /* ... */ }
});


Also popular now: