When I first got into Javascript, it wasn’t obvious to me how best to use the language to do a simple model-view-controller.
I’ve heard of backbone, spine, and some other javascript mvc frameworks, but I just wanted to start with something really simple. My friend Jonas came up with a good example showing how our thinking has evolved after building some stuff.
Option 1: Prototype
In the prototype method you define your functions using the javascript prototype construct and then make use of ‘this’ and ‘self’ to make sure you are calling your methods with the right javascript context.
This is how we first stared doing simple mvc.
FormModel_literal.js
var FormModel = function(){}; FormModel.prototype.getInputText = function(){ return $('#inputtext').val(); }; FormModel.prototype.setInputText = function(value){ $('#inputtext').val(value); };
FormController_prototype.js
var FormController = function(pModel){ this.model = pModel || new FormModel(); this.fill_clicked = function(){ this.model.setInputText('Hello World'); }; this.clear_clicked = function(){ this.model.setInputText(''); } }; FormController.prototype.init = function(){ var self = this; $('#fillbutton').click(function(){ self.fill_clicked(); }); $('#clearbutton').click(function(){ self.clear_clicked(); }); }; FormController.prototype.getModel = function(){ return this.model; };
It’s nice. It works. You don’t need to worry about state (it’s all in the model). But you do need to watch context (this, that, and self) and it’s easy to get wrong if you aren’t careful.
Option 2: Literal method
In the literal method, you use the javascript literal construct to keep most internal methods private, and then only expose those you want publicly consumed in the return statement.
FormModel_literal.js
var FormModel = function(){ function getInputText(){ return $('#inputtext').val(); } function setInputText(value){ $('#inputtext').val(value); } return { getInputText : getInputText, setInputText : setInputText } };
FormController_literal.js
var FormController = function(pModel){ var model = pModel || new FormModel(); function fill_clicked(){ model.setInputText('Hello World'); } function clear_clicked(){ model.setInputText(''); } function init(){ $('#fillbutton').click(function(){ fill_clicked(); }); $('#clearbutton').click(function(){ clear_clicked(); }); } return { init: init, model : model }; };
I think it’s elegant and nice. And I didn’t even know you could use a return statement like that in Javascript.
The advantage of this method is you don’t have to worry so much about getting the context wrong (this, that and self) as it’s all in the same context.
And it’s just easier on the eyes for me as it more closely resembles the classical OO model I am used to in Java and C#.
You can hook these up in view a test page as follows:
<html> <head> <script type="text/javascript" src="jquery-1.6.1.min.js"></script> <!-- Using function returning an Object literal (my preference) --> <script type="text/javascript" src="js/controllers/FormController_literal.js"></script> <script type="text/javascript" src="js/models/FormModel_literal.js"></script> <!-- Using Prototype --> <!--<script type="text/javascript" src="js/controllers/FormController_prototype.js" ></script>--> <!--<script type="text/javascript" src="js/models/FormModel_prototype.js"></script>--> <script type="text/javascript"> $(document).ready(function() { new FormController().init(); }); </script> </head> <body> <input type="text" id="inputtext" name="inputtext" value="" /> <input type="button" id="fillbutton" value="Fill with Text"/> <input type="button" id="clearbutton" value="Clear"/> </body> </html>
So while both methods will work, we are currently leaning towards option 2 (the literal method).
It just seems cleaner, less stuff to worry about, and it looks good. Of course being relatively new to hard core javascript, and still looking for better ways, we reserve the right to change our minds tomorrow.
If you have any tips, better ideas, or feedback, we’d love to hear them.
Update:
Nice write up along similar lines from Ola Bini.
Oct 26, 2011 @ 13:09:52
Its this kind of critical thinking and analyzing problems that makes programming so enjoyable.
Bookmarks for October 26th from 09:51 to 23:42 | gregs
Oct 26, 2011 @ 23:07:35
Oct 27, 2011 @ 02:36:47
Agreee, Literal method is easier to digest. Anything particular you are loosing by not utilizing Prototype method?
Oct 28, 2011 @ 13:15:34
I don’t think so. The readability is what speaks to me with literal.
Some of the guys mentioned the prototype method declaration is more ‘efficient’ than others (not sure if that’s performance, memory or what).
Oct 27, 2011 @ 02:42:06
Something I don’t quite get about this line:
var model = pModel || new FormModel();
Since it’s a function that returns an anonymous type object, I would use it as a function:
var model = pModel || FormModel(); // no new operator
Oct 28, 2011 @ 13:18:15
I am not sure what the here would be between returning new vs just returning the function. Anyone?
Nov 02, 2011 @ 16:55:09
Using the new keyword ensures that the new object contains all of the internal attributes of the base object. Best description I’ve seen of this is on Stack Overflow at:
http://stackoverflow.com/questions/1646698/what-is-the-new-keyword-in-javascript
Nov 03, 2011 @ 16:47:51
Great description – thx Fio.
Nov 08, 2011 @ 18:29:33
I have found this:
“Rather than class definitions, JavaScript has constructor functions and the new operator. A constructor function can specify an object’s initial properties and values when it is instantiated. Any JavaScript function can be used as a constructor. Use the new operator with a constructor function to create a new instance.
The new operator changes a function’s context, as well as the behavior of the return statement. In practice, using new and constructors is fairly similar to languages with native class implementations”
Bookmarks for October 26th through October 27th | gregs
Oct 27, 2011 @ 23:02:23
Bookmarks for October 28th from 09:43 to 16:53 | gregs
Oct 28, 2011 @ 23:03:02
Bookmarks for October 29th from 00:03 to 23:37 | gregs
Oct 29, 2011 @ 23:09:07
Bookmarks for October 29th through October 30th | gregs
Oct 31, 2011 @ 00:02:02
Jan 16, 2012 @ 19:36:40
(1) You realize that option 1 works more or less as a Class from which multiple instances can be created. Options 2 is more like a static class in which every “new” just gets you references to the single static model property and methods.
(2) Defining methods directly on the prototype, as in your Option 1 model, (NOT your option 1 controller!), insures that there is only one function object created for each method, whereas defining the functions in the constructor (as in your controller) makes a separate function object for each method for each instance of controller!
Neither are a problem is there is only going to be one instance of model and controller, but for general OOP technique, it makes a difference.
Jan 16, 2012 @ 21:31:14
oops…i said that wrong…option 2 WILL get you separate objects (not like a static), but it will create a separate function object for each inner function for each object instance created by calling FormModel and FormController (which by the way option 2 would not use “new” when calling FormModel/FormController because it would create an object that just got thrown away since your “constructor” is creating its own object in the return statement).
Jan 18, 2012 @ 15:00:39
Thanks for the clarification Bruce. Good points.
For me it comes down sometimes to style and ease of use.
Option 2 for me is currently my favorite because I just like how the code looks and behaves.
It’s not perfect (sometimes I can’t Jasmine tests things the way I would like) but it’s probably more a lack of my Javascript skills than option 2 not working.
Thanks though for your thoughts. Always good to hears more pros, and differences between different approaches.
Cheers
Feb 18, 2012 @ 14:29:17
Brilliant intro into the DIY MVC, i’m a big fan of learning how it all works before adopting a framework, so thanks!
I have a question though, how would you go about loading in data on navigate to that page? So an example would be to click a link that has a parameter of an id & then the browser goes to that page with id in the request, goes to your DB, reads & loads data into the model which the view can show.
Any links or snippets of code you could show me would be brilliant.
Thanks
Mark
Feb 18, 2012 @ 19:46:01
My JavaScript MVC framework (gravey.org) has example applications that do that sort of thing. I.E. load initial single page app into browser via the initial HTML/JavaScript load, and then dynamic events trigger data to be loaded into Models (or saved back to server) via AJAX. [The UI events are translated into Commands (ala Command Design Pattern) so that a global Undo/Redo stack can be implemented.] For a summary diagram of the pattern, see blog entry: http://polyglotinc.blogspot.com/2012/02/cheat-sheets-for-mvcce-my-refinement-on.html
Jun 26, 2012 @ 19:51:20
This is not an example of MVC when there is no View……
Sep 13, 2012 @ 12:43:51
Lol, the View is the HTML part stupid fool XD
Примеры простых MVC приложений на JavaScript « Веб-мастерская
Sep 10, 2013 @ 16:08:01
Feb 08, 2018 @ 20:57:40
var FormModel = function(){
this.getInputText = function(){
return $(‘#inputtext’).val();
};
this.setInputText = function(value){
$(‘#inputtext’).val(value);
};
};
var FormController = function(){
// || mean ‘or’
var model = new FormModel();
this.fill_clicked = function(){
model.setInputText(‘Hello World’);
};
this.clear_clicked = function(){
model.setInputText(”);
};
this.init = function(){
var self = this;
$(‘#fillbutton’).click(function(){ self.fill_clicked(); });
$(‘#clearbutton’).click(function(){ self.clear_clicked(); });
};
this.getModel = function(){
return this.model;
}
};
What about this? only have been used ‘this’ keyword. not using return statement.