Here is the textbook standard way of describing a 'class' or constructor function in JavaScript, straight from the Definitive Guide to JavaScript:
function Rectangle(w,h) {
this.width = w;
this.height = h;
}
Rectangle.prototype.area = function() {
return this.width * this.height;
};
I don't like the dangling prototype manipulation here, so I was trying to think of a way to encapsulate the function definition for area
inside the constructor. I came up with this, which I did not expect to work:
function Rectangle(w,h) {
this.width = w;
this.height = h;
this.constructor.prototype.area = function() {
return this.width * this.height;
};
}
I didn't expect this to work because the this
reference inside the area
function should be pointing to the area
function itself, so I wouldn't have access to width
and height
from this
. But it turns out I do!
var rect = new Rectangle(2,3);
var area = rect.area(); // great scott! it is 6
Some further testing confirmed that the this
reference inside the area
function actually was a reference to the object under construction, not the area function itself.
function Rectangle(w,h) {
this.width = w;
this.height = h;
var me = this;
this.constructor.prototype.whatever = function() {
if (this === me) { alert ('this is not what you think');}
};
}
Turns out the alert pops up, and this
is exactly the object under construction. So what is going on here? Why is this
not the this
I expect it to be?
I think the right answer is that you should not do this because as kennebec said in the comment:
If you have a hundred rectangles, you are going to redeclare that prototype method a hundred times.
I thought that 'this' always referred to the object against which the function was called.
The meaning of this
depends how the function was called:
this
usually refers to the object the function is called from at runtime, e.g. when called as ob.foo()
, this
in foo will refer to ob.foo()
, this
refers to the global variable (the top object that contains all other global variables in your js program)..call()
and .apply()
, the object that this
refers to is supplied.Now, if you wanted a way to point to the object for the function that your function was created in (i.e., the 2nd level this
at the time of creation), then you would have to rename the deeper this
to make it shine through the currently-visible one. If that's clear as mud, this should help clarify a bit:
function outside() {
// Here, 'this' refers to the object outside() is called with.
// Let's "rename" this, to make it visible to inside functions.
var that = this,
private = 42;
return {
inside: function {
// here, 'this' refers to the object inside() is called with,
// it is hiding outside's this.
// Also, 'that' refers to the object outside() was called with,
// *at the time* outside was called and inside was created.
// Notice that you can see 'private'
// (but nobody outside of 'outside()) can!
return private;
}
}
}
This pattern above is useful to create object with public methods that can access private members. See Crockford for probably better explanations.
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