Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

for, for-in, forEach, string concatenation and the ||-operator

Hi, I've been experimenting with JavaScript and have a few questions with regards to the code I've been trying out (AFAIK, this is not related to any of the treehouse videos though).

What I have here is a function, addNumbers() that takes any number of arguments and adds them together if they are numbers and displays an error if there are no arguments or if one or more are of an invalid type. It does it correctly with my first two functions (myFunc1 and myFunc2, outputting to sum1 and sum2) and incorrectly in the third, which I've commented out (myFunc3 and sum3).

function addNumbers() {
  if (arguments.length === 0) {
    return "Error. No numbers added.";
  } else {
    var sum1 = myFunc1(arguments);
    var sum2 = myFunc2(arguments);
    //var sum3 = myFunc3(arguments);
  }

  return "\nmyFunc1 returns " + sum1 + "\nmyFunc2 returns " + sum2 
  //+ "\nmyFunc3 returns " + sum3;
}

function myFunc1(argArray){
  var sum = 0;
  for (i = 0; i < argArray.length; i++) {
    sum = sum + argArray[i];
  }
  return checkValid(sum);
}

function myFunc2(argArray) {
  var sum = 0;
  for (i in argArray) {
      sum = sum + argArray[i];
    }
  return checkValid(sum);
}

// function myFunc3(argArray) {
//   var sum = 0;
//   argArray.forEach(function(i) {
//     sum = sum + i;
//   });
//   return checkValid(sum);
// }

function checkValid(outcome) {
  if (typeof outcome !== "number") {
    return "Bad value";
  } else {
    return outcome;
  }
}

Now, my questions are:

  1. Is for, for-in or forEach preferred over the others in a case like this?
  2. the forEach method doesn't work because my argArray is apparently not an array, even though it clearly looks like one when I do a console.log of it. Is this because of compatibility issues or have I made a mistake in the code?
  3. Does it make sense here to pass the arguments as an array to the other functions?
  4. I was originally looking for a Python-esque for ... in loop that loops over the values. If forEach doesn't work, for of is currently unsupported and for each in is deprecated, is there an alternative?
  5. My return statement in the addNumbers() function looks ugly because of the string concatenation. I looked around for a string format method, but it seems that there isn't one and I have to add it manually to the String prototype, is this correct? (talking about something like "This is a {} string".format("formatted"))
  6. In my checkValid() function, I've used the NOT operator. But what if I wanted to use the OR/|| operator without having to repeat myself? Would I have to do if ((typeof outcome === "string") || (typeof outcome === "undefined")) or is there some way to avoid repeating the left side of the statement?

Sorry for the wall of text and thanks for the answers, if any :)

1 Answer

Well, I've come up with my own answers. In case anyone is interested, here's where I went wrong in my original code:

arguments is an object that acts like an array but isn't actually an array (the .isArray method will return false). To be able to use forEach on arguments, I had to convert the arguments object into an arguments array first with the following function:

function createArray(argObject) {
  var argArray = [].slice.call(argObject);
  return argArray;
}

I then used that function in myFunc3 to get the same result as the other two:

function myFunc3(argObject) {
  var argArray = createArray(argObject);
  var sum = 0;
  argArray.forEach(function(i) {
    sum = sum + i;
  });
  return checkValid(sum);
}

As for performance, I still have no idea what's better, but a simple for or for-in loop is definitely easier than adding an extra function to convert the arguments object into an array. That said, converting it allows you to sort the arguments, pop them off and other such manipulations.

For string concatenation, I understand now that to be able to add a format method, I have to make it myself and add it to the String prototype, using regular expressions to find and replace content in a string. I suppose it's not too hard, but it's too bad there isn't a built-in method to do this though.