Why do I need to use `return`?

This lesson is so wrong. lol. I believe the tasks are backwards. Why do I have to use the return keyword before declaring the variables, in this case numOfMonitors? The examples wasn’t like that.

The exercise to this Return lesson should be like this and not otherwise:

function monitorCount(rows, columns) {
  const numOfMonitors = rows * columns;
  return numOfMonitors;
}

console.log(monitorCount(5,4))

That’s how the example is shown, so please be consistent, because it get’s you stuck, or if it’s going to change, let us be aware of that with the theory, etc.

13 Likes

Shoquim thank you for pointing that out, this example was confusing as it was not like the ones before.

I think they changed it because in coding there is more than one way to do the same thing. So they were maybe trying to show you a different way.

1 Like

Yeah, I was having trouble here couldn’t figure out what I was doing wrong. Initially I had this:

function monitorCount(rows, columns) {
const numOfMonitors = monitorCount(5,4);
   return rows * columns;
  }
console.log(numOfMonitors);

and it gave me a ReferenceError “numOfMonitors” is not defined. After googling this error, I found out that numOfMonitors in the above code was out of scope, so then I did this and it worked for me:

const numOfMonitors = monitorCount(5,4);
function monitorCount(rows, columns) {
   return rows * columns;
  }
console.log(numOfMonitors);

So, yes, I certainly think there was more than one way to approach this lesson. So far this has been the only one to throw me off though. Good luck to everyone else learning! ^-^/

6 Likes

Thanks for that. It got me confused indeed. This helped clarify things.

My take on this exercise, is that there are two alternatives that result in the same answer, as follows:

1. The exercise asks for:

function monitorCount(rows, columns) {
return rows * columns;
}
const numOfMonitors = monitorCount(5, 4);
console.log(numOfMonitors);

2. Whereas, the example used in the initial explanation would suggest:

function numOfMonitors(rows, columns) {
const monitorCount = rows * columns;
return monitorCount;
}
console.log(numOfMonitors(5, 4));

I actually found it a positive thing that this confused me a bit at first, as it made me think harder about how the different sections of code were interacting.

I can see that both sets of code give the same final result, but that the key difference seems to be whether the variable is defined within the function (alternative 2) or outside of it (alternative 1).

For the moment, I can see this theoretical difference, but I can’t yet grasp whether there are also any practical reasons why defining the variable within the function may sometimes be preferable, and sometimes not. This is something that will no doubt become clearer as I learn, practice and experiment more; but I’m also interested to know if anyone has any thoughts on this, or could guide me in the right direction… :thinking:

9 Likes

In this example, monitorCount is completely superfluous. The first example simply returns the computed value directly.

The variable is outside of the function so it can act as a reference to the return value, and thereby retain it for further use. There is conceivably some need for the computed value, other than just to print it. Once the second example logs the return value it is lost.

2 Likes

That’s really helpful, thanks @mtf. What’s getting people confused is the initial example given in the exercise:

function rectangleArea(width, height) {
  let area = width * height;
}
console.log(rectangleArea(5, 7)) // Prints undefined

It then goes on to suggest (in a diagram) that the appropriate solution to undefined is to insert return area; as follows:

function rectangleArea(width, height) {
  const area = width * height;
  return area;
}
console.log(rectangleArea(5, 7)) // Prints 35

I realise now that the example may only do it this way to make it easier to demonstrate the importance of return. But as you can see from other posts above, there does seem a tendency for the learner to latch onto the example as a normal way of expressing things. Perhaps, a comment to the exercise editors about this from someone with more experience might help to make it clearer?

A couple of people @andrerferrer @tbel0 have also mentioned that it isn’t made clear why undefined is returned if return + value is omitted from the function body. At first, I just took this at face-value as a fact. However, I do think it would help people to know why previously we didn’t need to include return + value in the function body, when we included console.log() there instead, for example:

function rectangleArea(width, height) {
	console.log(width * height);
}
rectangleArea(5, 7);

Is that because in the the function body console.log() acts like return? And if so, why?

1 Like
function rectangleArea(width, height) {
  let area = width * height;
}

Two things to take note of in the above…

  1. No return (moot, at this point)
  2. let declaration; area cannot be accessed outside of the function.

The following calls the function, but in return it gets undefined because of no return.

console.log(rectangleArea(5, 7))

The lesson informs us that when no return is specified, JS returns undefined. What it doesn’t inform us of (though it may be the plan for future lessons) is that we cannot access area,

console.log(area)
! Uncaught ReferenceError: area is not defined

For the fun of it, remove let from the area declaration.

function rectangleArea(width, height) {
  area = width * height;
}

Now call it, without logging.

rectangleArea(5, 7)

Now log area again.

console.log(area)    // <- 35

I only bring this up because in order to understand return, and the reasoning behind it, we need to recognize, scope. When we wrote, let area = ... we declared the variable in local scope; hence, it was not accessible. When we wrote, area = ... it was automatically declared in global scope, and why we could access it after we ran the function.

It should come up about how this pollutes the global namespace, so I won’t go into it, now. Just know that we are leading up to best practice and definite intent when naming and using variables, and how to move data around without corrupting the program.

Notice how we were able to move 5, and 7 into the function’s local scope just by passing them as arguments? And inside the parameter list we gave them names by which to be known in that scope?

We successfully bridged the gap between our caller, global scope, and our function body, local scope. The data is there by reference. The values are in memory (likely right in the code as the literals we gave) and JS knows how to find those values by their given names.

Once we compute the product of the two values to arrive at an area, it’s up to us what to do, but if I were the caller I’d want that data sent back to me, and not just printed. It needs to be useful to the program, too, not just the user.

So the bridge back to the caller is the return statement by which we can transfer the data up to that scope.

function rectangleArea(width, height) {
    return width * height;
}

area = rectangleArea(5, 7)
console.log(area)    // <-  35

We need to realize that functions are utilities, first and foremost. Their chief role is to store and make accessible upon demand (a call) the utility of a code block. That we can pass in arguments which parameters accept and which are treated locally, evaluated or computed in some way and an outcome given back (returned) is their real benefit since that lets us use functions to manipulate data in safe, protected enclosures. What happens in a function, stays in a function. Ring any bells?

It’s an in the moment thing since they haven’t envisioned any further use for the data they see on the screen, and haven’t considered how it might be captured for further use. This is very common, and a tricky question to address.

As I’ve done above, more or less, to first show the function without a return so learners might get aquainted with undefined. I cannot speak for the author nor do more than speculate as to their motive and reasoning, and it is not even my intention now to disseminate it. I merely tell it in my own words and hope it doesn’t pour gasoline on an already glowing ember.

8 Likes

Wow, thanks!

It took several re-reads for some of that to sink in, but it was well worth the effort. Clearly, there are some concepts, such as scope, that I won’t properly grasp until further on in the courses; but you’ve managed to draw back the curtain just enough to give me a very helpful peak, without blinding me :sunglasses:

I totally get that when learning, you sometimes need to have more questions than answers for some concepts, and accept that some of the ah ha! moments won’t come until later. In order to really grasp some concepts you often need that confused and uncomfortable stage to start with, as some things need to be mulled and turned over in your mind for longer than others, and often you need to wait for other things to click into place first.

Anyway, in saying that, I agree with your overall take on how to approach the challenges of this particular exercise, and your post definitely provides some very helpful extra support and food for thought for those that want to dig a bit deeper :+1:

4 Likes

I think that’s a pretty good attempt at an explanation! :slightly_smiling_face:

I was struggling with this a few weeks back, but it becomes much clearer a bit further on, when you start learning about scope.

As @mtf says in one of his posts above:

Just to clarify things a bit more, here: this is if we try to print to the console with console.log(area) outside of the function. If we were to put console.log(area) within the function (after the let area variable) and then call the function with rectangleArea(5, 7), then the area would be printed. However, the main purpose of a function…

I hope this confirms things, rather than confusing them further! :wink:

exatly what i had i could not figure it out…

The following would actually be the best for demonstration purposes for this exercise:

function monitorCount (rows, columns) {
const numOfMonitors = rows * columns
return console.log(numOfMonitors);
}

Now use the function with different parameters to get different values on the console. For example:

monitorCount(3,4);

I think their intention was to show that the return expression can take both objects and expressions.