📜 ⬆️ ⬇️

Binds class mutator.

In a discussion of a recent topic, the habrasoobschestvo 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 from one of the MooTools developers. In this topic I present a translation of an article in which Jan Kassens describes an example of the use of class mutators.

While writing a class, you may need to bind a class method to an event as a handler and use this inside 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 as long as it does not reach the removal of the event handler, since Function::bind() works in such a way that it returns a new function wrapping the original. Therefore, you need to save the same wrapper somewhere to remove the handler (without removing all the event handlers of the element, which is not very good inside the portable class).

Note the author of the translation . The author of the article is referring to the case when an event handler is assigned using el.addEvent('click', myFn.bind(this)) . Thus, it cannot be removed using el.removeEvent('click', myFn.bind(this)) , because bind() will return a new function that was not 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 to third-party classes.

What I have seen several times is an object containing all the associated functions that is created in the constructor, as can be seen from the example:
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 () { /* ... */ }
});

I did not like this decision, because it is too cumbersome: why should I use this.bound.myFn whenever I use the this.bound.myFn functions? And then, I do not want to bind these functions manually each time. After reviewing 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 “ Binds class mutator”. Many of you may not have heard of class mutators before, but have definitely used them when writing your classes. Built-in mutators: Implements and Extends , and here’s the Binds code:
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 the methods passed to it in rows by new versions tied to the instance. Binds: 'foo' simply bind foo to the class, Binds: ['foo', 'bar'] bind foo and bar . Pretty simple, isn't it?

Now let's see how much simpler the class is using the Binds mutator:
var MyClass = new Class({
Binds: [ 'sayHello' , 'sayGoodbye' ],

initialize: function (){
// this.sayHello
// this.sayGoodbye
},

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

I hope you understand a little and can find a use for this.

Source: https://habr.com/ru/post/40059/


All Articles