How to idiomatically structure JavaScript
I've been reading O'Reilly's JavaScript: The Definitive Guide (6th ed), and have been examining the very first example program -- a loan calculator. However, the structure of this just bugs me -- I know that it's a book example, and hence probably not the best way of going about things for the sake of simplicity, so I'm curious as to how a professional using 开发者_运维知识库best practices would structure the same thing.
For example, the main function, calculate(), which is called onChange to any of the input fields, contains within it a TON of stuff that doesn't have anything to do with calculating anything -- display code, for instance -- how would you pull that out to separate concerns?
It'd make me feel better if you could modularize the individual tasks that are to be done and put the major control into the function something like this:
run() {
getdata();
calculate();
if (isFinite(monthly)) {
display();
save(arg1, arg2, arg3, arg4); }
else {
cleardisplay(); }
But I have no idea what I'm talking about. Is there some way to do it with the Object Literal pattern? I guess I'm just asking how you would do it idiomatically.
This is a very contrived example, but you can see some concepts here on how to separate "business logic" from both the input data and the display output. I've used jQuery here just for the $
, .val()
, and .click()
helper functions, you could use any other library, or none at all.
HTML:
<p>First Number</p>
<p><input type="text" id="num1"></p>
<p>Second Number</p>
<p><input type="text" id="num2"></p>
<p>Third Number</p>
<p><input type="text" id="num3"></p>
<p><input type="button" value="Calculate" id="btntrigger"></p>
<p>Result</p>
<p><input type="text" id="result"></p>
Javascript:
function Calculator(options) {
this.options = options;
}
Calculator.prototype.run = function() {
return (parseInt(this.options.getN1()) + parseInt(this.options.getN2())) *this.options.getN3();
};
var calc = new Calculator({
getN1: function() { return $('#num1').val(); },
getN2: function() { return $('#num2').val(); },
getN3: function() { return $('#num3').val(); },
});
$('#btntrigger').click(function(){
$('#result').val(calc.run());
});
Live Demo: http://jsfiddle.net/Wd49U/
Some notes:
The input is handled by passing in callback functions which return the value to be used, this callback style offers extreme flexibility in where and how you want to get your data into the calculator.
I assign the "click" handler outside of the calculator function because that method of triggering it, isn't really the calculators responsibility, maybe in another case you would want to call run()
on a timer, or from another event.
Most importantly, it really depends on your specific use case for what the best way might be. I hope this helps you get some ideas.
You may be interested in reading Object-Oriented Javascript
The example in your reference is perfectly okay, Javascript is, after all, a scripting language. But since it supports a good model for Object-Oriented Programming by prototyping, it is arguably better to use this approach.
The loan calculator would be something like this:
//create an object LoanCalculator
function LoanCalculator(amt, apr, yrs, zipcode) {
this.amt = amt;
this.apr = apr;
this.yrs = yrs;
this.zipcode = zipcode;
}
//create the function calculate for LoanCalculator
LoanCalculator.prototype.calculate() {
//your code here...
}
...
then the call would be something like this:
function getDataFromDisplay() {
var dataFromDisplay = new Object();
dataFromDisplay.amt = document.getElementBy...
...
return dataFromDisplay;
}
function myOnchangeFunc() {
var data = getDataFromDisplay();
//use the LoanCalculator object you created
LoanCalculator lc = new LoanCalculator(data.amt, data.apr, data.yrs, data.zipcode);
lc.calculate();
}
This way, codes are more modularized. However, for introductory Javascript programming, it already introduces a lot of new concepts which may not be suitable for early exercises. So in most cases, introduction to Javascript uses "procedural" method instead of "object-oriented" which is, again subject to debate, easier to understand.
And later in programming life, you will be bugged by Javascript problems such as browser compatibility issues and you will ask yourself, "Can I focus more on my real problem rather than fixing these annoying issues?" Then you will find Javascript frameworks such as the one mentioned by ctcherry, JQuery, to be very useful.
Well, there's no real architecture in this sample to speak of. This approach is somewhat reminiscent of the pre-Spreadsheet era, when each time someone had a new calculation task they'd hire a Fortran programmer to implement it...
So if you wanted to see a better separation of concerns, one place to look might be a JavaScript spreadsheet implementation. Just typing that as a search into Google yielded this, and I don't know if it'd be more to your liking or not:
http://101.lv/learn/JSweek/ch12.htm
I've noticed that culturally speaking, JavaScript seems to be based on assuming a lot of things are taken care of for you by the dynamic HTML. There isn't as much of the concept of "phasing" in the architecture, setting clear architectural boundaries between the part of your program that updates data structures and the part that does the drawing. The reason you don't get "screen dirt" or other artifacts of GUI programming is just based on trust of the increasingly fast browsers to take care of everything behind the scenes. So you're probably going to find a lot of interweaving of program logic and page updates.
It's just a simple example, it isn't meant to be object-oriented.
Most design patterns can be implemented with JavaScript, this book may help: http://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X/ref=sr_1_1?ie=UTF8&qid=1312266239&sr=8-1
I've read it, it's ok. In my opinion John Resig's book 'Pro JavaScript techniques' is the best in order to learn JavaScript the good way: http://www.amazon.com/Pro-JavaScript-Techniques-John-Resig/dp/1590597273
Good luck with the reading
精彩评论