I am asking this from a language design point of view. So I am trying to find out
this
?I don't think making "this" unbound was a mistake. It can sometimes be confusing at first, but there are good reasons for the way it is. The first one that comes to mind is that, since JavaScript is not a class based language, functions are not associated with any specific class, so there's not a consistent way to automatically bind "this" to the correct object instance. For example,
function Person(first, last, age) {
this.firstName = first;
this.lastName = last;
this.age = age;
}
Person.prototype.getFullName = function() {
return this.firstName + " " + this.lastName;
};
"this" needs to refer to a Person object, but the function assigned to Person.prototype.getName doesn't have any way of knowing how it's going to be used, so "this" needs to be bound to whatever object it is called on.
Where this causes a problem, is when you have nested functions.
// This is a really contrived example, but I can't think of anything better
Person.prototype.getInfo = function() {
// get name as "Last, First"
function getNameLastFirst() {
// oops. "this" is the global object, *not* the Person
return this.lastName + ", " + this.firstName;
}
// expect something like "Crumley, Matthew: Age 25",
// but you get "undefined, undefined: Age 25"
return getNameLastFirst() + ": Age " + this.age;
};
The syntax artificialidiot suggested would be convenient, but it's pretty easy to bind "this" to a specific object using apply:
function bind(func, obj) {
return function() {
return func.apply(obj, arguments);
};
}
Person.prototype.getInfo = function() {
// get name as "Last, First"
var getNameLastFirst = bind(function () {
return this.lastName + ", " + this.firstName;
}, this);
return getNameLastFirst() + ": Age " + this.age;
};
or the more "traditional" method using closures:
Person.prototype.getInfo = function() {
var self = this;
// get name as "Last, First"
function getNameLastFirst() {
return self.lastName + ", " + self.firstName;
}
return getNameLastFirst() + ": Age " + this.age;
};