Search code examples
javascriptpublicprototype-programming

Javascript: Accessing public method of prototype does not work


I want to create a simple class in Javascript with only one public function as follows:

function A(myTitle) { 
    var title = "";
    this.getTitle = function() {
        return title;
    };
    title = myTitle;
};

var anInstance = new A("first");
console.log("anInstance.getTitle(): '"+anInstance.getTitle()+"'"); 
// expecting to return "first"

This does work as expected.

Now I want to add this class as a prototype to a new class, that includes a new title variable, so that the getTitle() method returns the value of the variable instead:

var myA = new Object();
myA.title ="second";
myA.prototype = anInstance;
console.log("myA.getTitle(): '"+myA.getTitle()+"'"); 
// expecting to return "second"

But instead of the expected "second", it results in the following error:

TypeError: 'undefined' is not a function (evaluating 'myA.getTitle()')

What is the problem with this function access?

Update: The key point for my question is the following: In my application I will create several thousand instances of type "A" and several more of other comparable types. Thus memory efficiency and performance do matter. So I thought it would be great to create the according methods (several more will follow, getTitle is only one example) only once and the "data objects" reference these methods. Is this possible?


Solution

  • If all you want is instance variables (and that's all I see you using), what's wrong with idiomatic JavaScript:

    function A(title) { 
        this.title = title;
    };
    
    A.prototype.getTitle = function() {
        return this.title;
    };
    
    var anInstance = new A("first");
    var myA = new A("second");
    

    You can implement both Self-like prototypal OO and Smalltalk-like class-based OO on top of JavaScript, but this only makes sense in case of inheritance hierarchies, where the flat model of JS (which favors composition over inheritance - it's easy to add new methods to the prototype or apply() arbitrary constructor functions, but you'll have to jump through some hoops to make inheritance work properly) is not sufficient.

    As to why your code can't work: your getTitle() method returns a lexical instead of an instance variable, which takes no part in property resolution via the prototype chain and thus can't be overwritten your way; also, .prototype is a property of constructor functions which is used to initialize the internal [[Prototype]] property of newly created instances - setting .prototype on general objects has no effect whatsoever on property resolution.