Friday, April 3, 2015

Dude bro, JavaScript's bound functions are stupid

Too many times I've come upon this comment or question, "What happen to 'this'?" If you haven't caught on JavaScript is a fucked up language. It has quirks that you have to work around. One of these is it's JavaScript's Scope behavior which is the root of "What happen this to 'this'?".

Let's take a simple example from Java.

public class Person {
    public String fname;
    public String lname;
    public String getFullName() {
        return this.fname + " " + this.lname;
    }
}

In this case, the getFullname method is bound to each instance of a Person object so when I say:

Person dude = new Person();
dude.fname = "Jay";
dude.lname = "Pax";
dude.getFullName(); // returns "Jay Pax"

I know that this in the getFullname() refers to dude. The binding of this in which I'm running getFullName() is dude, a specific instance of Person.

In JavaScript , functions don't behave like this. They don't have bound methods. In fact, they can be unbound and rebound at the coder's whim.

For example, if I have:

var getFullName = function(){
    return this.fname + " " + this.lname;
}

There is no obvious context that this should refer to.
So now let's go a step futher and say I wrote something like this:

function foo(){
    return this.fname + " " + this.lname;
}
var getFullName = foo;

That's not much different. We don't know what this is referring to exactly. So getFullName still doesn't have a clearly-defined this binding.

So let's give it one:

var dude = {
    fname: "Jay",
    lname: "Pax",
    getFullName: function(){ 
        return this.fname+ " " + this.lname;
    }
};
dude.getFullName(); // returns "Jay Pax"

Well now! That's starting to make sense. Until you do something like this:

var doAThing = dude.getFullName;
doAThing(); // returns "undefined undefined"

Waaaaattttt......

You see, when I pointed the variable doAThing at dude.getFullName, I pointed it a the function of getFullName NOT the object dude. So we lost the this binding in the process.

I know it's fucked up but it's fixable you'll have to use Function.bind.