3 ms·
The this/that antipattern is one reason I dislike the class pattern. I avoid it by using prototypes: SomeClass = function (arg1) { // Hopefully do someth
by ksenzee 10y ago
The this/that antipattern is one reason I dislike the class pattern. I avoid it by using prototypes:
SomeClass = function (arg1) {
// Hopefully do something more interesting than this, indeed. :)
this.arg1 = arg1;
};
/**
* Assigns foo to the instance variable bar.
*/
SomeClass.prototype.method = function (foo) {
// Hopefully you do something more interesting than this, too!
this.bar = foo;
};
someClass = new SomeClass();
someclass.method(foo);
Then when I need a handler for a DOM element, I bind the instance to the method:
someClass = new SomeClass();
var handler = someclass.method.bind(someclass);
$('.link').click(handler); // using jQuery as easy-to-read DOM shorthand; it's not required
Or if I'm creating the handler within the class:
/**
* Creates a click handler for <a class="link"> elements.
*/
SomeClass.prototype.init = function () {
var handler = this.method.bind(this);
$('.link').click(handler);
};
Over the years I've found it really easy to maintain code written like this. There's no callback hell, you don't even need Promises, and everything is easy to document. But often I find myself in an environment where I'm maintaining someone else's code, and I can't just refactor everything, so I grit my teeth and use 'that' or 'self'. I like your idea a lot better.
- andrewstuart2 10y agoThe main reason I've come to avoid prototypes in many cases (except when I really need to control memory) is that you can't keep any kind of information private (via closure) and share it across instance methods. It has to be a property on the instance, and is therefore accessible to anybody with access to the instance. Conventions (like prefixing with _) are great, but they can only help loosely enforce encapsulation and provide no form of real privacy.
- WorldMaker 10y agoYou can combine the two, creating a closure for private variables and using proper prototypes. The easiest way now is the ES2015 class keyword and its syntax, but for older versions of JS there are patterns and practices (and about a zillion helper libraries) to do so.
- learc83 10y agoI just use factory functions that return an object that has arrow functions as properties, then I get private information via closures, and I don't have to worry about dealing with this. https://www.youtube.com/watch?v=ImwrezYhw4w https://www.youtube.com/watch?v=ImwrezYhw4w
- WorldMaker 10y agoPlus the prototype pattern is more idiomatic JS and combines better with other OO libraries than the class constructor pattern in top comment. Also, the ES2015 class keyword is syntactic sugar for the best of both worlds of the prototype pattern, combined with the private variable support of the class pattern. It does the right thing with both `this` and `super` (which is possible but tough with the prototype pattern and nearly impossible or at least crazy tough to do right with the class constructor pattern) and is as useful/important to replacing that = this/self = this antipatterns as arrow functions are.
- acjohnson55 10y agoWhy would you consider it an anti-pattern? To me, that term implies that an idiom has some sort of pitfall. Like using `==`, for instance. But `that = this` is actually pretty robust. Although, I'd say arrow functions are the better solution if all you need is a callback. Pervasive usage of `bind` drives me mad. It can patch over problems if you're using it locally, but if a function is being passed around, it invisibly has different behavior from a normal function with dynamic `this`. It also is quite noisey, in my opinion. Using methods of an object to contain the sequences of an async process is handy. But it's not as flexible as promises, because it only works if the async process is self-contained. Promises are far more composable, which is important for modular processes. And with `async` functions, they allow native flow control structures to cross async boundaries. By comparison, a the methods+callbacks approach feels like programing with GOTO in BASIC.