0

This works:

function Bird(name){
    Animal.call(this,name);
    this.speak = function(){
        console.log("Tweeet!");
    }
}
Bird.prototype.constructor = Animal;

This throws "Cannot set property 'constructor' of undefined"

function Bird(name){
    Animal.call(this,name);
    this.speak = function(){
        console.log("Tweeet!");
    }
    this.prototype.constructor = Animal;
}

Why would that be? In the second example, this should be Bird as I have called the function with new, so I should be able to set the prototype of this. What am I missing here?

2
  • 2
    this inside function - object, so it don't have prototype property, but if you change this to Bird all should work Commented Mar 2, 2015 at 10:08
  • Just answering my own question, now that I understand JavaScript a little better. In the second example, 'this' is not 'Bird' - 'this' is a new object that has been created and passed to the Bird function. Commented Sep 30, 2015 at 8:14

1 Answer 1

2

An Object instance (this) does not have a prototype property, so this.prototype returns undefined.

You have two options to get around this:

  1. Call Bird.prototype as you did in the first snippet:

    function Bird(name){
        Animal.call(this,name);
        this.speak = function(){
            console.log("Tweeet!");
        }
        Bird.prototype.constructor = Animal;
    }
    
  2. Use Object.getPrototypeOf to get hold of the prototype of the object:

    function Bird(name){
        Animal.call(this,name);
        this.speak = function(){
            console.log("Tweeet!");
        }
        Object.getPrototypeOf(this).constructor = Animal;
    }
    

Option 2 is more useful when you don't know what type the object is. In your example, you are inside the Bird class, so option 1 makes more sense.


Here is a working example which will hopefully make the question in your comment clearer:

// 1. Tell Javascript what an Animal is
// This will create an Object called Animal, but it is a blueprint not an actual Animal.

function Animal(name)
{
    this.name = name;
}

// 2. Tell Javascript what a Bird is
// This will create an Object called Bird, but it is a blueprint not an actual Bird. So it cannot speak!

// or function Bird(name){
var Bird = function(name){
    Animal.call(this,name);
    this.speak = function(){
        alert("Tweeet! said " + this.name);
    }
    
    Object.getPrototypeOf(this).constructor = Animal;
};

// 3. Now create an actual Bird which can speak 

var tweety = new Bird("Tweety Pie");
tweety.speak();

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Rhumborl. I think I may be misunderstanding how functions work. This is how I think it works: As JS has no classes, when I define function Bird(){} that function is instantiated as an object on the current context. Am I wrong here? Can a function exist that is not an instantiated object?
@wagster try see about new operator. When you define function - you define function, when you instantiate object - you instanteate object
@wagster Yes what you are saying sounds correct but you may be mixing up the types of objects. In JS, everything is an object, including functions, so function Bird(){} will create an object of type Function with name Bird in the current scope. In fact to make it clearer you can write it as var Bird = function(){}. At this point, no Birds actually exist, you have just told JS how to create one. If you want an actual Bird, you will need to use var canary = new Bird("Tweety Pie"). It is this call which will actually run your Bird method and give you an object of type Bird.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.