Reputation: 11409
I am trying to fix some Javascript that uses functions and prototype functions. For some reason the prototype function is always undefined when I try to access it and I can't figure out why.
Here is a simple example of what I'm trying to do. Basically, I want to reference the _open
prototype from within the original Container
function declaration using this
.
Container();
function Container() {
alert(this._open);
}
Container.prototype._open = function() {
alert("hey");
}
You can see in fiddle that it just alerts "undefined." But this question and this question both show examples of people doing this. Why do I keep getting undefined?
Upvotes: 2
Views: 1260
Reputation: 82267
Your code takes advantage (perhaps unintentionally) of hoisting. So it looks like the prototype is built prior to execution but in fact it was not.
This is what your code actually looks like
function Container(){
alert(this._open);
}//functions are "hoisted"
Container();
Container.prototype._open = function() {
alert("hey");
}
Looking at this, it is clear that when Container()
is called that the assignment to the prototype has not happened yet. Not only that, but Container()
is being called like a function and not like an instantiation. What happens when Container
is called like a function is that the this
binding does not occur. The end result is that this
takes on the global reference (assuming the script is not in strict mode). The global reference at this point does not have a reference to a _open
property and as a result undefined
is alerted and that is all that happens.
In order to have this to actually alert the function _open as defined here would be to first assign the property ._open
to the prototype of Container
before instantiating. Otherwise, that property will not exist in the created object.
Next, the instantiation must be used with the new
keyword. This will call the functions constructor, set up its own execution context which comes with a ThisBinding
and some environments for variables.
All in all, that would look like this
//place the definition at the top for readability
//so it is obvious that it is declared first
function Container(){
alert(this._open);
}
//Next ensure that the _open property is defined on the prototype before
//instantiating the object
Container.prototype._open = function() {
alert("hey");
}
//Lastly, ensure that the keyword `new` is used to start the
//process of instantiation
new Container();
Upvotes: 1
Reputation: 3513
Call Container()
after the definition and with the new
evaluator : var instace = new Container();
function Container() {
this._open();
}
Container.prototype._open = function(e) {
alert("hey");
}
var instance = new Container();
And maybe you don't need two alerts.
Upvotes: 1
Reputation: 39248
function Container() {
this._open();
}
Container.prototype._open = function() {
alert("hey");
}
var container = new Container();
Try the above. You need to create an instance of the object using new
.
Otherwise this
refers to the global object and not the prototype members.
Using constructors without new() causes weird bugs. Since this
will refer to the global objected === window.
Upvotes: 2
Reputation: 5737
Three things:
new Container();
instead of Container();
.new Container();
line AFTER all prototype
additions.this._open();
instead of alert(this._open);
to actually execute
the function.So your code should look like this:
function Container() {
this._open();
}
Container.prototype._open = function() {
alert('open');
}
new Container();
Hope this helps.
Upvotes: 8