198

In knockout js I see View Models declared as either:

var viewModel = {
    firstname: ko.observable("Bob")
};

ko.applyBindings(viewModel );

or:

var viewModel = function() {
    this.firstname= ko.observable("Bob");
};

ko.applyBindings(new viewModel ());

What's the difference between the two, if any?

I did find this discussion on the knockoutjs google group but it didn't really give me a satisfactory answer.

I can see a reason if I wanted to initialise the model with some data, for example:

var viewModel = function(person) {
    this.firstname= ko.observable(person.firstname);
};

var person = ... ;
ko.applyBindings(new viewModel(person));

But if I'm not doing that does it matter which style I choose?

Kev
  • 118,037
  • 53
  • 300
  • 385
  • I don't believe there is a difference. I usually use the constructor pattern, as I often have methods which I prefer to declare on the `prototype` (methods that often, for example, fetch data from the server and update the view model accordingly). However you could still obviously declare them as a property of an object literal, so I can't really see a difference. – James Allardice Mar 06 '12 at 18:17
  • 4
    This has nothing to do with knockout, and everything to do with ease of instantiation of custom objects in JavaScript – zzzzBov Mar 06 '12 at 19:01
  • 1
    @Kev if the viewModel is a constructor function you write it in UpperCase just like var PersonViewModel = function(){...}; – Elisabeth Apr 23 '13 at 19:36

2 Answers2

256

There are a couple of advantages to using a function to define your view model.

The main advantage is that you have immediate access to a value of this that equals the instance being created. This means that you can do:

var ViewModel = function(first, last) {
  this.first = ko.observable(first);
  this.last = ko.observable(last);
  this.full = ko.computed(function() {
     return this.first() + " " + this.last();
  }, this);
};

So, your computed observable can be bound to the appropriate value of this, even if called from a different scope.

With an object literal, you would have to do:

var viewModel = {
   first: ko.observable("Bob"),
   last: ko.observable("Smith"),
};

viewModel.full = ko.computed(function() {
   return this.first() + " " + this.last();
}, viewModel);

In that case, you could use viewModel directly in the computed observable, but it does get evaluated immediate (by default) so you could not define it within the object literal, as viewModel is not defined until after the object literal closed. Many people don't like that the creation of your view model is not encapsulated into one call.

Another pattern that you can use to ensure that this is always appropriate is to set a variable in the function equal to the appropriate value of this and use it instead. This would be like:

var ViewModel = function() {
    var self = this;
    this.items = ko.observableArray();
    this.removeItem = function(item) {
         self.items.remove(item);
    }
};

Now, if you are in the scope of an individual item and call $root.removeItem, the value of this will actually be the data being bound at that level (which would be the item). By using self in this case, you can ensure that it is being removed from the overall view model.

Another option is using bind, which is supported by modern browsers and added by KO, if it is not supported. In that case, it would look like:

var ViewModel = function() {
    this.items = ko.observableArray();
    this.removeItem = function(item) {
         this.items.remove(item);
    }.bind(this);
};

There is much more that could be said on this topic and many patterns that you could explore (like module pattern and revealing module pattern), but basically using a function gives you more flexibility and control over how the object gets created and the ability to reference variables that are private to the instance.

Martlark
  • 14,208
  • 13
  • 83
  • 99
RP Niemeyer
  • 114,592
  • 18
  • 291
  • 211
  • 1
    Great answer. I often use a function (using revealing module pattern) for complex objects like viewmodels. But for simple models, I use a function so i can handle everything in one place. – John Papa Mar 06 '12 at 23:40
  • 1
    @JohnPapa - just been watching your PluralSight video on knockout (just over half way through - and, coincidentally, just watched the section on object literal vs function). Really well done and has helped the penny drop. Well worth a month's subscription for that alone. – Kev Mar 07 '12 at 11:41
  • @Kev - Thanks. Glad you are getting value out of it. Some wont care about that module as its not really a Knockout concept, more of JavaScript patterns. But I found as I got further with Knockout that those concepts really helped me create cleaner more stable code. Anyway, glad you enjoy it :) – John Papa Mar 07 '12 at 14:31
  • shouldn't be self.items = ko.observableArray(); in your second example? You used this, is it correct? – JackNova Jun 15 '12 at 22:33
  • 1
    @JackNova in the constructor function `self` and `this` are the same, so either will be equivalent. In the removeItem function, `self` does become more useful, as `this` would no longer be the current instance when executed in the context of a child item. – RP Niemeyer Jun 16 '12 at 01:22
12

I use a different method, though similar:

var viewModel = (function () {
  var obj = {};
  obj.myVariable = ko.observable();
  obj.myComputed = ko.computed(function () { return "hello" + obj.myVariable() });

  ko.applyBindings(obj);
  return obj;
})();

Couple of reasons:

  1. Not using this, which can confusion when used within ko.computeds etc
  2. My viewModel is a singleton, I don't need to create multiple instances (i.e. new viewModel())
paulslater19
  • 5,869
  • 1
  • 28
  • 25
  • This is revealing module pattern if not mistaken. Good answer but the question was not about this pattern. – Phil Jul 23 '13 at 21:43
  • @paul : Sorry to ask for old thread. u said `My viewModel is a singleton, I don't need to create multiple instances (i.e. new viewModel()) ` but it is not clear what u trying to say `I don't need to create multiple instances ` can u plzz come with more usage so one can understand the advantage of your approach. thanks – Mou May 29 '15 at 11:07
  • IMO, one of the reasons you would declare ViewModel as a `function` is because you would execute it more than once. However, in my example about, it's an immediately-invoked anonymous function, so it will not be created more than once. It's very similar to the Object Literal in the above example, but gives you more isolation – paulslater19 May 29 '15 at 12:34