Existem algumas vantagens em usar uma função para definir seu modelo de exibição.
A principal vantagem é que você tem acesso imediato a um valor this
igual à instância que está sendo criada. Isso significa que você pode fazer:
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);
};
Portanto, seu observável calculado pode ser vinculado ao valor apropriado de this
, mesmo se chamado de um escopo diferente.
Com um objeto literal, você teria que fazer:
var viewModel = {
first: ko.observable("Bob"),
last: ko.observable("Smith"),
};
viewModel.full = ko.computed(function() {
return this.first() + " " + this.last();
}, viewModel);
Nesse caso, você pode usar viewModel
diretamente no observável calculado, mas ele é avaliado imediatamente (por padrão) para que você não possa defini-lo no literal do objeto, como viewModel
não é definido até que o literal do objeto seja fechado. Muitas pessoas não gostam que a criação do seu modelo de visualização não seja encapsulada em uma chamada.
Outro padrão que você pode usar para garantir que this
seja sempre apropriado é definir uma variável na função igual ao valor apropriado de this
e usá-la. Seria assim:
var ViewModel = function() {
var self = this;
this.items = ko.observableArray();
this.removeItem = function(item) {
self.items.remove(item);
}
};
Agora, se você estiver no escopo de um item e chamada individual $root.removeItem
, o valor de this
será realmente os dados vinculados nesse nível (que seria o item). Usando self neste caso, você pode garantir que ele esteja sendo removido do modelo de vista geral.
Outra opção está usando bind
, que é suportada por navegadores modernos e adicionada pelo KO, se não for suportada. Nesse caso, seria semelhante a:
var ViewModel = function() {
this.items = ko.observableArray();
this.removeItem = function(item) {
this.items.remove(item);
}.bind(this);
};
Há muito mais a ser dito sobre esse tópico e muitos padrões que você pode explorar (como padrão de módulo e padrão de módulo revelador), mas basicamente o uso de uma função oferece mais flexibilidade e controle sobre como o objeto é criado e a capacidade de referenciar variáveis que são privadas para a instância.
prototype
(métodos que, por exemplo, costumam buscar dados do servidor e atualizar o modelo de exibição de acordo). No entanto, você ainda pode obviamente declará-los como propriedade de um objeto literal, portanto não vejo realmente diferença.