First of all, your code is pretty good. No big errors as you fear, there are comments, right indentation, anyone can understand it easily, and... it works !!!
Yet let me suggest a few improvements you could make to make it shine :
For all your functions : use a function declaration : it's easier to use since you can use them anywhere in your code (and not only after the var statement was actually evaluated), and the global namespace pollution is the same anyway.
The sum() function just doesn't make sense as it stands : Why one would use sum(i, 3) instead of i+3 ?
It makes sense again with one or both of those features : type checking or accepting any number of arguments.
To type-check or not to is a big debate i won't enter into. I did here since it might be a good way to learn to be cautious about types even in 'typeless' Javascript.
So following code does both type checking and accepting any number of arguments :
// returns the sum of its arguments (0 if none). // throws if any of them is not a number. function sum() { var result = 0; for (var i=0; i<arguments.length; i++) { var thisNumber = arguments[i]; if ((+thisNumber) !== thisNumber) { throw('Error : argument ' + i + ' of sum is not a number ('+thisNumber + ').'); } result+=thisNumber; } return result; }
For range() : change the arguments name to start and end makes understanding the function goal easier.
To give step a default value, you don't want to test step against null, but rather against undefined. (it worked because because you used ==, but notice that by using '==null', you're just testing is ?? falsy ?, so the wrong input 0 for step will silently be changed to 1.).
You might want to check :
• that start, end, and step (if provided) are meaningful numbers (see above).
• that sign(end-start)==sign(step) so end might indeed be reached.
• that start-end is a multiple of step. Otherwise you don't get end in the range, which i find most annoying.
• that step is not === 0. In fact the previous check already checked that.
// returns an array filled with the range of numbers between start and end, // using a optional step that defaults to 1. // throws if the range cannot be built with the provided arguments. function range(start,end, step){ // step defaults to 1 if (step === undefined) step = 1; // type-check start, end, step here if you wish // ... // checking that step sign allows to reach the end if ((end-start)*step<0) { throw ('the sign of step does not allow to reach end value'); } // checking that step value allows to reach the end value // btw will check that step !==0 also var stepCount = (end-start) / step; if ( stepCount - Math.floor(stepCount) !==0) { // division has remainder ? throw('cannot reach '+end+' starting from '+start+' with the step ' + step); } // build result array var result = []; for (var i = start; i != end ; i += step) { result.push(i); } return result; };
For rangeSum i was surprised to see that you didn't re-use the range function you just wrote : In fact you re-wrote a simple version of range.
I think only two options are relevant :
1) re-use range, and add an optional step argument for free.
2) if you just want to do a most simple range sum function, go for a for loop and sum by yourself.
I choosed (2) :
You might want to check :
• that start, end are meaningful numbers (see above).
• that that end can be reached with a step of 1 <==> that (start < end) and start, end are integers. ( x === 0 | x )
// returns the sum of numbers ranging from start to end(included). function rangeSum (start,end){ var result = 0; // you might want to check some things here. for (var i = start; i <= end; i++) { result += i; } return result; };
... But in fact, with just a little bit of math, you can write the simple version of rangeSum in one line : :-)
function rangeSum(start, end) { // you might want to check some things here. return (end + 1 - start)*( end + start)/2 ; }
Edit :
To allow easier understanding :
1) I used Math.floor to floor the stepCount. ( you might forget about the 0 | stepCount dirty trick for now ). So when i write if ( stepCount - Math.floor(stepCount) !==0) i test if the division has a remainder.
2) ((+thisNumber) !== thisNumber) is a trick to test for thisNumber not being a number or NaN. How ?
a) On the left side, we convert thisNumber to a number, so since we use !==, thisNumber has to be from a different type from number => for now it's quite like testing if (typeof thisNumber === 'number').
b) But NaN qualifies as a number ( ... ... ), so since NaN !== NaN, the expression above does also consider thisNumber as wrong if its value is NaN.