Recently I have an argument with a friend who absolutely hate the this keyword in Javascript. He claims that since the language has an ambiguous binding of this in different situations, e.g. const f = obj.g will lose the binding to obj, obj.g.call(obj2) will call g in the context of obj2..., the this keyword in Javascript is simply one of the worst thing in Javascript.
He also claims that Javascript would be a lot easier to code/maintain by avoiding the use of this keyword. He advocates the following pattern for object creation:
function Car() {
const car = {};
car.position = 0;
car.move = () => car.position++;
return car;
}
new Car();
// or
Car();
I am, on the other hand, very comfortable with the this keyword. I use it a lot and appreciate how bind, call and apply works. However, I can't really find a legit argument against his pattern, because it really seem to be clearer for those who don't know much about Javascript?
What do you think? Give me some insights!
Oldest comments (39)
I think I agree with your friend. I don't hate the this keyword, I use it quite a lot myself. But I feel like the keyword this is prone to more errors than code trying to avoid it. Obviously, it all depends on the programmers writing the code.
To me, it seems safer to try to avoid using too much this. It also reads better I believe. When I'm reading code, I wouldn't want to ask myself every 2 lines: What is this this referring to?
This I think really depend on the design of your system.
In angular/vue/react, the framework seem to have developed around the keyword
thiswithout an issue. I wonder why they have made this choice ifthiscould be troublesome.I use React quite often. So, I use this a lot. I use arrow functions all the time, so every single this I use refers to the outer most instance, the component, every single time. Definitely a personal preference anyway :)
the only advantage that I could think of using
thisis the ability of reusing functions. Using the method suggested by my friend will create a new function instance for every object created. But if we use class, essentially we are using prototype, so all the methods will only be defined once. It makes a difference when we are creating the same instance many many times.It completely shatter the prototype which is bad IMO. Your friend's method not only create a new function each time, but prevent any ineritance.
Also, it's not possible to supercharge Car's prototype.
The "this" keyword can be tricky, but avoiding it leaves you in a land without OOP.
Yeah, but in react click handlers and other stuff most of the time need this, which leads to you either abusing class properties for arrow functions or having bind everywhere
that was. mostly for the class base component i suppose
I have no reason for it, nor do I use JS a lot in my work. But whenever I do I avoid using this, as I just feels too ambiguous. I like being very clear and direct in my code, and if that means I need an extra two lines, that's just the way I prefer it.
Though in a lot of cases it would have made things a lot easier for me.
It's sneaky. I've wasted a decent amount of time and effort due to forgetting that
thisisn't bound in fat-arrow functions, or having a different binding than I expect at whatever point in the code. I still like usingthis, but I'm not sure I could mount a bulletproof defense of it.I mostly agree with your friend, and I think ES6 has made it worse, because of how anonymous functions "break" the rules, which just confuses the hell out of junior devs:
I also kind of hate how everyone invents their own convention for re-assigning
thisto avoid context problems like so:Having said that, it's use is extremely prevalent, so I wouldn't make a crusade of this. It's a lot being that guy who's always complaining that everyone uses the phrase "begging the question" wrong.
Arrow functions were made specifically so that the second example wouldn't have to happen anymore. Consider the following.
Ignoring how terrible that code is, arrow functions allow you to have functions in functions while still maintaining the scope of your parent, yes but this behavior was very much requested and intended
I agree that this is a good thing....if you are senior enough at javascript to understand the nuances of the scope of
thisand you understand how arrow functions interact with this differently than "traditional" ones -- to many junior devs,() =>is just shorthand forfunction(). The fact that it isn't is mostly the fault ofthis-- and is that extra "thing you need to know" really worth keepingthisaround?I've always had a love/hate relationship with magic variables (back when I first encounterd
$_in perl my mind was a little blown).I can completely understand how avoiding them makes for more readable code.
Using
thisin any language is a hallmark of doing anything in OOP. Yes, JS has some things to watch out for, but the idea anyone would consider trying to drop usingthisaltogether instead of learning the time/place and make making great things so much easier escapes me.Because I come from the word of c++/python amd haven't done anything majorly oop in js
thisseems unpredictable to me. But I don't know how much you should optimize your code readability for language newcomersWhile there are some historical gotcha's when using
thisin certain contexts, if you plan to use JavaScript in an OOP sort of way, I would in no way say that you should steer away from usingthis. On top of that, constructors should not be defined with functions anymore. They should be in aclasswhere usingnewis forced and the meaning ofthisis unambiguous.Secondly I would greatly avoid using
.bindor.callas much as you can. Some of the easiest ways to lose track ofthisis using functions in this way..Switch to ts
I am guessing when you do
obj.fnin typescript, you still lose binding, no?There are no ambiguous bindings for the keyword
this. They are very predictable. Some frameworks decide to change the bindings and that is the issue.One thing about the pattern that your friend advocates is that it would be harder to use
instanceof.You would have to do:
Have you seen Douglas Crockford's talk during Nordic.js 2014? There he said that he stopped using
Object.create,new,this, etc. completely and instead uses the factory pattern for creating objects, similar to the pattern of your friend (around 25:00). After watching the video I tried it out and from then on I never missed these keywords. I rarely use the factory pattern nowadays, just if I really need it. Instead I try to code more functional