I am asking this from a language design point of view. So I am trying to find out
this
?this
was a mistake, or could be improved upon?To clarify why I'm uneasy about this
, consider this example:
var a = {};
a.f = function(){ return this; }
var f = a.f;
// f() != a.f()
Note how easily the object to which f()
belong is lost: separated from a
, this
becomes the global object (window
for browsers).
Now consider:
var newA = function(){
var self = {};
self.f = function(){ return self; }
return self;
}
var a = newA();
var f = a.f;
// f() == a.f() !
Without using this
at all, we are able to establish and maintain the object context regardless of where or how the method is used. I can't help but think that, with the power that closures provide, this
becomes superfluous, and perhaps even a little dangerous...
I'm not on some vendetta against this
, or looking to start an argument; I'm merely trying to better understand it. I do appreciate that 'this' can be useful, but recognize that it can be confusing as well... Certainly confusing to beginners, and perhaps to experts as well in sufficiently obscure cases.
And yet, it remains a heavily-used and seemingly well-respected part of the language, in a time when other core aspects of the language seem fair game for shunning (i.e., Crockford and with
or new
). What am I missing then, that makes this
indispensable?
The 'this' keyword refers to the current object/function/method that they are working with and it's not peculiar to Javascript, it's also available in other languages as well, but here in Javascript it behaves differently compared to those languages.
“This” keyword refers to an object that is executing the current piece of code. It references the object that is executing the current function. If the function being referenced is a regular function, “this” references the global object.
this losing context In order for a function to know on which object to work, this is used. this represents the function's context. this loses context in many situations. It loses context inside nested functions, it loses context in callbacks.
The this keyword refers to the current object in a method or constructor. The most common use of the this keyword is to eliminate the confusion between class attributes and parameters with the same name (because a class attribute is shadowed by a method or constructor parameter).
You seem to be expecting this to behave as it does in certain OO languages, where it always refers to the object a method belongs to.
But in JavaScript, a function can be attached to multiple objects, or no object at all. In your example, you've written a function intended to be used in the context of one specific object... But nothing prevents me from taking that function and attaching it to any other object. That's just the nature of the language - functions are first-class, object membership is optional.
Therefore, this refers to the context in which a function is called. Right now, that's either an arbitrary object (specified via .
, .apply
, or .call()
) or the global object. In future versions of the language, it will refer to the context in which the function was defined: the global object for global functions, the outer this
for inner functions; you can view this as a correction of a design flaw, as in practice being able to refer to the global object using this was not particularly useful.
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;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With