Using prototype on view model functions - worth it?

1,255 views
Skip to first unread message

John Papa

unread,
Jun 1, 2011, 1:32:02 PM6/1/11
to KnockoutJS
I've been testing the idea of making my functions on the view models
use prototype. The properties I leave alone, but the functions I made
use prototype. The thought behind this was to avoid the functions
being created for every instance of the object. I want the properties
created for each instance, but there is not need for a remove
functiojn, for example, to be recraeted each time.

It all works, but I am curious how others feel about this. I don;t see
many examples of folks doing this with KO.

Of course, I realzie that the likelihood of creating 1000's of view
model instances and consuming a ton of memory because I did not use
prototype is probably pretty slim. I'm just trying to get a sense for
the "best" way to do it.

rpn

unread,
Jun 1, 2011, 2:09:34 PM6/1/11
to knock...@googlegroups.com
I think that putting functions on the prototype is the best option, especially when dealing with collections of objects.   I assume that many of the samples do not follow this pattern, just to keep it simple or because they don't deal with much data.  

I know that I don't typically do it for small samples, but it certainly doesn't take much more effort, so I really should be doing it that way.

John Papa

unread,
Jun 1, 2011, 2:11:51 PM6/1/11
to KnockoutJS
I hear ya.

The trick with them on a viewmodel is that sometimes your functions
that should be on the prototype need to reference something in the
viewmodel instance. So you have to either pass it in or scope it. Not
a big deal, but it can get harder to read and I suspect that is
another reason folks skip it.

JP

Joel Dart

unread,
Jun 1, 2011, 2:59:57 PM6/1/11
to KnockoutJS
that's primarily why I don't do it, though functions in prototypes can
also close over objects. Since the this keyword isn't bound to any
object, you can also ensure there's only one instance of a function
created by declaring your function outside your viewModel function
scope and closing over it.
(function () {
function add4() {
this.val( this.val() + 4);
}
nsObj.Constructor = function () {
this.add4 = add4;
};
}());

I find since I'm already adding in several dependentObservables, it
reads just as well to do

var vm = {
//simple/default value observables
};
//mapped observables tacked on

//dependent observables

//methods on vm

this makes my code pretty predictable so I can navigate more easily
and also makes jslint a little happier as it typically guarantees my
properties will be declared before use. Consequently, if you're using
visual studio, I've found it makes the intellisense run a little
faster (probably for the same reasons jslint runs better).

John Papa

unread,
Jun 1, 2011, 7:26:09 PM6/1/11
to KnockoutJS
Thanks for the tip. I rewrote my viewmodel to use that style. ABout
the same amount of code and I like some things better, as you
mentioned. But others seem awkward. So this stil you mention makes it
not necessary to handle prototype, whch is cool IMO. ANd it easily
separates out the methods, do's, properties ... again, cool. But 2
things stuck out to me in a not so great way:
1) i have a property and a function on my viewmodel that i want to
only be accessible from the public properties and functions. Basically
private ones. In this structure I had to expose the property on the
viewmodel {} so the function can access it later.
2) the functions now have to reference the viewmodel by fully
qualified name, as opposed to using scoping (shorter)

2 I could live with, but #1 seems awkward to me. How do you handle
"privates" ?

BTW ... here is my before and after viewmodel
before vm ... http://jsfiddle.net/johnpapa/KWU5e/
after vm ... http://jsfiddle.net/johnpapa/rH9Ef/


JP

Joel Dart

unread,
Jun 2, 2011, 10:58:45 AM6/2/11
to KnockoutJS
for 2, you don't have to. for all your methods it's really
unnecessary to fully reference since these are all methods instead of
pure functions. http://jsfiddle.net/rH9Ef/1/ In fact, that's why
dependentObservable has that second parameter: to allow you to set
what "this" is (a Function.prototype.bind wrapper if you will).

for 1, if there's anything you want to exist only privately but you
want to access later, you'd hide that inside a closure (I assumed "eh"
means you wished that was private) http://jsfiddle.net/rH9Ef/2/
properties are a little more tricky, because you then need an "own"
method instead of a prototypal method for each function that accesses
them since the function needs to close over the value.

//works
function MyObj (name) {
var private = name;
this.publicFunc = function () {
return private;
}
}

//doesn't work as private will change with each new class
(function(){
var private;
function MyObj (name) {
private = name;
}
MyObj.prototype.publicFunc = function () {
return private;
};
}());

but I can say that my idealism about separation of privates has
lessoned as I've dealt with debugging and just prepending _ to your
private properties and methods is really a lot easier, especially as
you can then access them from firebug directly without having a
breakpoint set in the right spot. Obviously there are use cases where
you must keep privates private, but in most cases I'm getting less
religious about it and moving to convention instead.

Joel Dart

unread,
Jun 2, 2011, 11:27:09 AM6/2/11
to KnockoutJS
Also, to be clear, the way I handle the big picture, privates,
constants, etc is generally through the format:

window.vm.personVm = (function () {

//constants & dependencies (basically what you're doing with the IIFE
and window but inline with the format)
var $ = jQuery, //note just using a comma here instead of semicolon
modelFactory = window.vm.modelFactory,
//private variables
personVm,//put here so private methods can access it and jslint stays
happy
private = "foo",

//private methods (usually done via variables thanks to originally
doing it that way)
myPriv1 = function () {},
myPriv2 = fucntion () {};//and finally the ;

//initialization
var vm = {
//simple/default value observables
};

//mapped observables tacked on

//dependent observables

//methods on vm

//return vm
return personVm;

}());

John Papa

unread,
Jun 2, 2011, 12:14:31 PM6/2/11
to KnockoutJS
Thanks for the feedback. The more I think about this the less I am
concerned with what is private or public. One way to do this is to
name privates with underscore prefixes by convention. Doesn't bother
me at all.

The //eh funciton is only public because I need the public functions
to access it. I'm not a big fan of prototype, honestly. Seems like
confusion just for the sake of it :) What I love about javascript is
its simplicity and how folks can pick it up easily.

I'm actually leaning between 3 different techniques:
1) declaring the object (like you suggested) then extending it with
the public stuff afterwards
2) using the revealing module pattern (JavaScript Design Patterns
book's name for it)
3) a hybrid approach

My goal is simplicity and readability, without breaking JSLint (the
best thing we have for a semblence of convention).


The one thing I keep going back and forth on is the idea of a
namespace. I am leaning heaviliy to using one for my own stuff now. I
was not originally, but I like having MY namespace to help de-pollute
the globals. (I now uppercase MY) Yes, its 3 more letters to type, but
I think it makes it clearer and more readable.


JP
> }());- Hide quoted text -
>
> - Show quoted text -

g.mavr...@gmail.com

unread,
Nov 21, 2012, 8:30:14 AM11/21/12
to knock...@googlegroups.com
Are you sure it works?
I have tried to set a function on the prototype (inside a dynaTable) where I wanted to sort by some column. So i had something like this:
dynaTable.prototype.sortColumn = function (column) {
        this._sortOptions({
            SortKey: column.SortKey,
            SortAsc: true
        });
    };

_sortOptions is an observable.

I called this from inside foreach (of columns) binding so I used: data-bind="click:$parent.sortColumn"
Guess what, "this" (inside the called function) was always mapped to column not to table...
Why is this happening?

Carlos Mendes

unread,
Nov 21, 2012, 10:56:40 AM11/21/12
to knock...@googlegroups.com
Hi John,

Apparently the link "after vm" is incorrect:  http://jsfiddle.net/johnpapa/rH9Ef/  Could you please make it available?

Just to confirm my reasoning (as I'm a newbie in KO and JS) this is only relevant when we use multiple viewmodels right?

Thks
Reply all
Reply to author
Forward
0 new messages