简体   繁体   中英

Can't access methods on object's prototype

I can create a Cat object and set a method on it's prototype to print out the cat's name.

 var log = function(message) { var results = $('#result'); results.append('<p>' + message + '</p>'); }; function Cat(name) { this.name = name; } Cat.prototype.speak = function() { log('My name is ' + this.name); }; var fluffy = new Cat('Fluffy'); var tiddles = new Cat('Tiddles'); log(fluffy.name); fluffy.speak(); log(tiddles.name); tiddles.speak(); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="result"></div> 

However, when I try to set the cat's prototype to an animal, I can't access the speak method:

function Animal(name, sound) {
    this.name = name;
    this.sound = sound;

    this.speak = function() {
        log(sound + '! My name is ' + name);
    };
}

function Cat(name) {
    this.prototype = new Animal(name, 'Meow');
}

var fluffy = new Cat('Fluffy');

fluffy.speak();  // TypeError: undefined is not a function

Why does fluffy not get the speak() method of its prototype?

If you want to learn how to do inheritance in JS, please read this guide . prototype is a property of the constructor function , not the instance .

Why does fluffy not get the speak() method of its prototype?

Because it's not on its prototype. You are never mutating Cat.prototype . The way you set up Animal , you would have to call Animal inside Cat instead:

function Cat(name) {
    Animal.call(this, name, 'Meow');
}

But if you want proper prototype inheritance, define speak on Animal.prototype and set up inheritance via Object.create :

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

Animal.prototype.speak = function() {
    log(this.sound + '! My name is ' + this.name);
};

function Cat(name) {
    Animal.call(this, name, 'Meow');
}
Cat.prototype = Object.create(Animal.prototype);

The problem is that you set speak as a privileged method inside Animal constructor.

However, that constructor is never called for Cat instances.

Moreover, you can't use prototype property to modify internal [[prototipe]] and change the object from which properties should be inherited. You can use non standard __proto__ or ECMAScript6 Object.setProtetipeOf , but better don't do that.

Instead, better use this approach:

function SuperClass(args) {
    // Here add SuperClass privileged properties
}

// Here add public properties to SuperClass.prototype

function SubClass(otherArgs) {
    // Add SuperClass privileged properties to SubClass instances:
    SuperClass.call(this, args);

    // Here add SubClass privileged properties
}

// Make SubClass instances inherit from SuperClass.prototype:
SubClass.prototype = Object.create(SuperClass.prototype);

// Fix constructor property, overriden in the line above
SubClass.prototype.constructor = SubClass;

// Here add public properties to SubClass.prototype

 function log(message) { document.body.innerHTML += '<p>' + message + '</p>'; } function Animal(name, sound) { this.name = name; this.sound = sound; } Animal.prototype.speak = function() { log(this.sound + '! My name is ' + this.name); }; function Cat(name) { Animal.call(this, name, 'Meow'); } Cat.prototype = Object.create(Animal.prototype); Cat.prototype.constructor = Cat; var fluffy = new Cat('Fluffy'); fluffy.speak(); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM