To answer your questions directly:
- Yes.
- Maybe. Depends on what you define as "better".
First, though: Don't use bracketed (aka subscripting) access to properties when regular dot notation works, e.g.:
window.Math.PI
is exactly the same as:
window['Math']['PI']
but a lot simpler.
Secondly, don't bother with window
when there's no need. window
is the global object in a browser's JS runtime, so you can just say
Math.PI
The exception to this is if you have variable shadowing, but that's outside the scope of this review.
Now, to tackle question 2 first, you could do this:
function calcCircleArea(r) {
if(r >= 0) {
return Math.PI * r * r;
}
return "invalid input";
}
It's quite subtle, but instead of having an else
branch, you just.. don't have an else
branch. If the first condition is true, the function returns the area - the rest of the function never runs. But if it's false, we skip straight past the if
block. The point of this is to ensure that the function always returns something. It already did that - there was nothing wrong with your code - but here it's even more explicit.
However, you could argue that handling invalid input is the less common option, hence that should be the thing to short-circuit the function, and return early:
function calcCircleArea(r) {
if(r < 0) {
return "invalid input";
}
return Math.PI * r * r;
}
In other words, you could assume good intentions (that the function will typically be called with proper arguments), and treat invalid input as the exception to the rule. However, you might be better served by having your function raise hell if its input is invalid. Right now you're returning something regardless of input, but maybe you want to completely bail out, if things aren't as expected (after all, a negative radius just doesn't make sense, so there's literally no good answer). Hence why I mentioned "exception to the rule", since exceptions, as concept, are made for that purpose. Now, exceptions are also a topic on their own, but in this case you could do:
function calcCircleArea(r) {
if(r < 0) {
throw "Invalid input";
}
return Math.PI * r * r;
}
throw
works the same as return
in the sense that the function just stops. But the caller has to handle it differently, or - if it's not handled - it'll bubble up as an error. But I digress.
Now, for question 1, yes, you can call the function from the HTML. In fact, you really should do that here, since you're currently using document.write
in a script that's placed in the head
element. Since document.write
happens immediately, your HTML actually ends up looking like this:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Circle area</title>
r = 7; area = 153.93804002589985<br />r = 1.5; area = 7.0685834705770345<br/>r = 20; area = 1256.6370614359173
</head>
<body>
</body>
</html>
because the browser reads the scripts, and runs it. Obviously, this isn't really valid HTML. Thankfully, a browser is very, very, very tolerant, and renders things just fine anyway, even if it makes no sense.
Now (still before actually answering your question), let me quickly point out that
- it's
<!DOCTYPE html>
with all-capital DOCTYPE
- since that doctype means HTML5, you don't need XHTML-style self-closed tags like
<br />
. Just write <br>
.
Finally, to answer your question, remove the three document.write
lines from your script, and use this HTML instead:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Circle area</title>
<script src="circle-area.js"></script>
</head>
<body>
<p>
r = 7; area = <script>document.write(calcCircleArea(7));</script>
</p>
<p>
r = 1.5; area = <script>document.write(calcCircleArea(1.5));</script>
</p>
<p>
r = 20; area = <script>document.write(calcCircleArea(20));</script>
</p>
</body>
</html>