Mike S
Mike S

Reputation: 11409

access prototype function from this

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

Answers (4)

Travis J
Travis J

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

Tiberiu C.
Tiberiu C.

Reputation: 3513

Call Container() after the definition and with the new evaluator : var instace = new Container();

Example

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

TGH
TGH

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

Tahir Ahmed
Tahir Ahmed

Reputation: 5737

Three things:

  • use new Container(); instead of Container();.
  • Move this new Container(); line AFTER all prototype additions.
  • Call 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

Related Questions