Search code examples
javascriptoopprototypal-inheritance

Should properties ever be on the prototype?


Below I've got a simple little inheritance chain in JavaScript:

var Base  =(function(){
          function Base(config){
            this.name = function(){
                return config.name;
            }
            this.department = function(){
                return config.department;
            }
        }
        Base.prototype.calculate = function(){
            return this.name().length + this.department().length;
        }
        return Base;
    })();
    var base = new Base({
        name: 'me',
        department: 'this one'
    });
    console.log(base.calculate());
    //inheritance
    var Concrete = (function(){
        Concrete.prototype = Base.prototype;
        function Concrete(config){
            Base.apply(this,arguments);
            this.number = function(){
                return config.number;
            }
        }
        return Concrete;
    })();
    var concrete = new Concrete({
        name: 'concrete',
        department: 'the best',
        number: 3
    });
    console.log(concrete.number()); //3
    console.log(concrete.name()); //concrete

and it works as expected. I'm curious, though about how correct it would be to place method properties on the prototype of an object. Canonically I know that instance data should go with the instance of the class and the methods the object actually uses should be on the prototype, but what about the situation where the properties themselves are methods (like name and department in Base in this example)? In the interest of keeping things immutable I'd rather not let users change the properties of one of these objects after they've been initialized. In this case does it make any sense to use the prototype instead of the constructor to add functionality to an object?

Or it is only correct to place properties in the constructor so you have access to them when you do something like Base.prototype.whatever?


Solution

  • what about the situation where the properties themselves are methods? In the interest of keeping things immutable I'd rather not let users change the properties of one of these objects after they've been initialized.

    I wouldn't call these "properties" any more, but "accessor" or "getter" methods.

    In this case does it make any sense to use the prototype instead of the constructor to add functionality to an object?

    Yes, if you mean functionality like calculate. If you mean getters like name, department or number you need to place them in the constructor as they need privileged access to the config.

    Canonically I know that instance data should go with the instance of the class and the methods the object actually uses should be on the prototype

    It's a bit different actually:

    • Everything instance-specific (data, accessor methods with distinct scopes) needs to go on the instance and is usually set up in the constructor
    • Everything that is shared amongst all instances (typically methods, but also data in some rare cases) should go on the prototype.
    Concrete.prototype = Base.prototype;
    

    No! Use Concrete.prototype = Object.create(Base.prototype); instead.