Javascript inheritance in Knockout ViewModels

Knockout provides an elegant way of updating the user interface using Javascript View models. Javascript has an inheritance model. With that, we can create a hierarchy of classes. Consider the following HTML with Knockout bindings.

<div id="main">
    <div data-bind="text: name"></div>
    <div data-bind="text: detail"></div>
</div>

We use a simple Model class. Load it with data. And bind it to the HTML.

var model = new Model();
model.load();
ko.applyBindings(model, document.getElementById('main'));

Simple inheritance

Klaus Komenda has an article on Javascript inheritance. As an example, we inherit the Model class from the BaseModel class.

function BaseModel() {
    this.name = ko.observable();
}

function Model() {   
    this.detail = ko.observable();
 }

Model.prototype = new BaseModel();

BaseModel has an observable named name.  And Model has an observable named detail. Since Model inherits from BaseModel, a Model object has both the name and detail observable properties.

Overriding functions

It is possible to override base class functions. Both BaseModel and Model classes define a load function. From the Model class, we can invoke the load function of the BaseModel class.

BaseModel.prototype.load = function () {
    this.name('a1');
}; 

Model.prototype.load = function () {
    // call base class method
    BaseModel.prototype.load.call(this);
    this.detail('a1 detail');
};

There is a good StackOverflow article that explains the benefits of declaring a function via prototypes.

Inheriting observable properties

Observable property in a Knockout View model is a function. All the objects of the derived classes share the same base class function. Any observable property defined in the base class is shared among multiple object instances.

In the above example, We create a collection of Model objects.

var model1 = new Model();
model1.name('a1');
var model2 = new Model();
model2.name('a2');

Both the Model objects share the same value for the name observable. In this case, both models have the same name value of a2. To overcome the problem, we use constructor inheritance as follows:

function Model() {
    var self = new BaseModel();
    self.detail = ko.observable();
    return self;
}

If multiple instances of the derived class are required, use constructor inheritance rather than prototype inheritance.

Related Posts

Leave a Reply

Your email address will not be published.