JavaScript: Abusing “this”

This post is an adaptation and expansion of a recent lightning talk I gave.  You can find the original slides here.

This

Let’s talk about the way  this works in JavaScript.

The first thing you learn when you’re studying JavaScript is that you can never assume it works the same way as another language.  For example, in a normal language,  this is a variable that is defined at compile-time.  It’s used within code to refer to a property on the current object you’re writing for. In JavaScript,  this means something else entirely.  It’s easy to miss the differences at first, because when used in a very straightforward manner,   this seems to exhibit some of the same behaviors.  It’s only when you start to experiment that everything breaks down.

If you’re like me, you probably once took an introductory web development class and had all of the confusing stuff with  this explained to you in the following manner, using the following code:

This is a fairly inaccurate way of describing what’s actually going on, and it shouldn’t take us long to poke some holes in it.

The first thing that should spring to mind is that myPublicProperty breaks as soon as we access it without the this keyword. Which is slightly weird. Also, we run into scenarios like below:

So we could play around with these edge cases all day, but there’s not much of a point.  If you’re really interested in getting a complete picture of what this actually is, I have a number of articles I’ll recommend at the bottom of the post. Otherwise, I’m just going to give you a quick interpretation that is, at least for our purposes, fairly accurate.

Assume that this is a global variable. When we call a method, this gets set to that method’s current scope. Per example, the below code :

Whenever you use this internally, you’re making a call to the object being stored in this global variable, and all of your data and method calls and so on happen relative to the object in that variable.  Simple enough, right?

Call and Apply

The important thing to remember is that JavaScript sets this at runtime, while the code is still executing. If we could change the definition of this before we called a method, we could do some cool stuff. And it turns out we can.

In fact, this is pretty much how JavaScript makes new objects in the first place.

What methods like  call allow us to do is to invoke a method and pass in an object that we want to use as the new   this for the duration of that method call.  And what that allows us to do is Object Oriented Programming on a very fundamental level.

Context is everything

For example:

JavaScript checks to see that a method exists before it allows you to call it, but it almost never checks to see that the method is being called in a context that makes any sense at all.  It’s not an oversight, it’s a feature.  But it’s a feature with a wild potential for abuse.

Another interesting feature of JavaScript is that it sometimes uses this internally.

We just got JavaScript to push an element onto the number 5, then pop it back off.  And the absolutely amazing, fantastic thing about all of this is that it worked perfectly.  No errors at all.

And yes, it’s a little bit tricky that we made a new number instead of sticking with a primitive, but the point still stands.

 A mild case of legitimacy

So, inheritance.  Here’s a fairly good method of doing it, as stolen from John Resig.

Wait, wait, don’t leave yet!  We can simplify all of this!

Good, you’re back.  So it’s not going to be as production ready, and we won’t get any of the nice typeof behaviors or even proper method overriding, but what if I told you we could get inheritance working in one line of code, without worrying about prototype or anything complicated like that?

In fact, let’s go a step farther and make multiple inheritance:

Easy, right?

All we have to do is take advantage of some of the things we already know about  this  and how objects get created in the first place.  We use our parent classes as constructors, but instead of making new objects, we just run those constructors with our new object as the current context.

Animal.call(this, "meow");

The result is that we’ve basically just chained two constructors together.  And again, half of object creation takes place in the constructor anyway, so we’re not really breaking any of the existing JavaScript tenants.

Again, there are some weaknesses with this method, many of which you can probably come up with on your own.

And there are many good questions you could ask right now that I’m not going to answer:

  • “What happens if I inherit from two parents that have methods or properties that share the same names?”
  • “What if I do want to have method overriding and be able to call base and super without breaking stuff?  How would I do that?”
  • “Isn’t it inefficient to be recreating all these methods every time I make an object?”

But still, if you were working on a tight schedule for a class or side-project, and didn’t really understand how the Prototype works, this would be a perfectly reasonable, if somewhat limited solution you could use in your actual code.

Yay, JavaScript!

Some follow-up links

To be expanded as necessary.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">