New to JavaScript, needing help with a function excercise

Hello everyone. I am learning JavaScript and am experimenting with a very simple task of printing something to the console using anonymous functions. I got the second part of the sentence to work but I am stuck on the first part.

var theNumber = (function(a,b){
  var number;
  a>b ? number = firstNumber : number = secondNumber;
  return number;
})(firstNumber, secondNumber)

var theBiggest = (function(a,b){
  var result;
  a>b ? result = "firstNumber" : result = "secondNumber";
  return result;
})(firstNumber, secondNumber)

var firstNumber = 5;
var secondNumber = 10;

console.log("firstNumber is " + firstNumber);
console.log("secondNumber is " + secondNumber);
console.log("The answer is " + theNumber + ". therefore " + theBiggest + " is bigger.");

It’s returning ā€œundefinedā€ in the console where I want the actual number where theNumber is. My goal is to have it return the bigger integer in the console, and then say therefore that the variable with that higher number is the bigger one.

ā€œThe answer is 10. Therefore secondNumber is bigger.ā€

Any help with concepts and better ways to think about it. My goal is to learn how functions work and I am as beginner as it gets. I won’t understand very high level stuff yet.

It’s choking because number is an integer, instead of a string. Return a string, and it’ll work.
Hint: you want to turn number in to String…

If I turn number into a string, won’t it return

ā€œThe answer is secondNumber. Therefore secondNumber is bigger.ā€

I recently moved the variables to the top and that seems to work:

var firstNumber = 5;
var secondNumber = 10;

var theNumber = (function(a,b){
  var number;
  a>b ? number = firstNumber : number = secondNumber;
  return number;
})(firstNumber, secondNumber)

var theBiggest = (function(a,b){
  var result;
  a>b ? result = "firstNumber" : result = "secondNumber";
  return result;
})(firstNumber, secondNumber)

console.log("firstNumber is " + firstNumber);
console.log("secondNumber is " + secondNumber);
console.log("The answer is " + theNumber + ". therefore " + theBiggest + " is bigger.");

Is that because the browser doesn’t know what to do with the variables until I define them first (top down rendering?

If you want to see the answer I made a JSFiddle → https://jsfiddle.net/Strider64/ndpr3x7h/23/

I give you a hint your is to look at your ternary statement that is where you are getting hung up at, not the anonymous function(s),

There’s nothing wrong with the ternary. It may not be the most concise ternary expression, but it’s a valid one.

You worked around the problem of the returntype by using textContent rather than string concatenation.

1 Like

Really Nothing wrong with his ternary statement? I don’t think so.

correct
var number = (a>b) ? firstNumber : secondNumber;

This gives an assignment or function call and instead saw an expression →
a>b ? number = firstNumber : number = secondNumber;

Even if it did work, it’s sloppy coding and diffidently would NOT work with ā€œuse strictā€;

If he wanted to do something the way your workaround would be something like this

var myAnswer = "Therefore the number "; 
myString = (a>b) ? myAnswer + firstNumber : myAnswer + secondNumber;

I was just using textContent as I didn’t want to use console.log in jsfiddle.

Actually, we’re both wrong.

The problem (as apparently the OP noted, and i completely missed… good job me.) is that firstNumber and secondNumber arent defined when theNumber is invoked. You accidentally solved the problem in your fiddle without noticing.

The ternary is perfectly legal, even in strict mode (at least according to my browser), but it doesn’t work if the input variables are undefined.

OP got ā€œsecondNumberā€ out of the other function because undefined is not less than undefined, so it fell through to the False condition.

My browser will happily execute the following code block:

"use strict";

var firstNumber = 5;
var secondNumber = 10;

var theNumber = (function(a,b){
  var number;
  a>b ? number = firstNumber : number = secondNumber;
  return number;
})(firstNumber, secondNumber)

var theBiggest = (function(a,b){
  var result;
  a>b ? result = "firstNumber" : result = "secondNumber";
  return result;
})(firstNumber, secondNumber)


console.log("firstNumber is " + firstNumber);
console.log("secondNumber is " + secondNumber);
console.log("The answer is " + theNumber + ". therefore " + theBiggest + " is bigger.");

Awesome! This is pretty much my first function I worked on from scratch so I feel like popping a bottle of champagne haha.

Thanks for the feedback. I want to be clear because I don’t want to get into bad syntax habits early on. Is the sloppiness of the coding due to lack of parentheses? Should an operation (is that the right word?) always be done that way in ternary statement?

[quote="seth702, post:9, topic:348081]
Is the sloppiness of the coding due to lack of parentheses? [/quote]

I don’t know why he thinks it’s sloppy, but I can explain problems that come to mind when I look at your code.

The line where theNumber Is assigned is confusing. First the opening braces leads to questions about why you are directly invoking the function. Secondly the unnamed function has me confused about what the function is supposed to do, and lastly the a,b variables give no indication of what they are.

The opening braces mean that I must scan down to the end of the function to see what’s passed into the function. It would be better if I didn’t have to do that.
The unnamed function has me scanning the whole function to try and interpret what it’s supposed to do, which is a big waste of time.
The a,b variables has me scanning the function yet again, to try and understand what the hell they are supposed to be.

The solution to all of that is to instead define a named function with well-named parameters, or to use an already existing function instead.

var firstNumber = Math.max(firstNumber, secondNumber);

Definitely not. I’ll have to write more on this later when time allows :slight_smile:

I see what you’re saying. That first exercise was specifically about whether I could do it with an anonymous function. I also had to write two separate functions because I was unclear about how to use an array, so it’s a pretty fluffy set of coding.

I had learned about named functions and came up with this, with an array so it’s leaner. Open to any critiques, tips etc.

function theNumber(a,b) {
   var result;
   a>b ? result = ["firstNumber", a] : result = ["secondNumber", b];
   return result;
 }

 firstNumber = 125
 secondNumber = 17

var numberResult = theNumber(firstNumber, secondNumber);

console.log(firstNumber);
console.log(secondNumber);
console.log(numberResult[1] + " is larger. Therefore, the bigger number is " + numberResult[0]);

If I’m understanding all this, the function is allowing me to compare a set of arrays, and it’s plopping the answer into the ā€œresultā€ variable so that ā€œtheNumberā€ is essentially the array that’s being chosen as a result of the greater than calculation. And that’s sitting there waiting to be used in another context. That’s pretty cool.

I was unclear as to why ā€œresultā€ wasn’t being used anywhere else, but the ā€œreturnā€ function gives it meaning by having a place to put the array and now ā€œtheNumber = [ā€œfirstNumberā€, a]ā€ IF a is greater than b. Is that basically what is happening?

I’m still a bit unclear as to when to use anonymous functions vs named, but I’m sure that will get clearer as I go.

my tip - focus on learning ES6 - declaring variables with Var is a big no no , instead use LET and CONST to declare variables - and saves you a lot of headache.

there is a free tutorial over at scrimpa dot com (remove the dot with . ) (have no clue if posting links are allowed in here sorry (first post) - that tells you the ins and out of ES6 - (scrimba. dot /g/ges6)

all you have to do is sing up for free and enjoy

Instead of critique from a person, I’ll use JSLint to supply the critique instead. It’s much easier to accept critique from an inhuman machine, than from someone else.

Expected ā€˜:’ and instead saw ā€˜=’.

Assignments within ternary statements are bad, as they easily lead to confusion.

A better solution is to assign the ternary to result.

I’ll comment out the old code to make it easier to see how we get from the old code to the new code.

   // var result;
   // a>b ? result = ["firstNumber", a] : result = ["secondNumber", b];
   var result = a>b ? ["firstNumber", a] : ["secondNumber", b];

Wrap a ternary expression in parens, with a line break after the left paren.

That’s kind of specific. let’s see what we get when we do that.

   // var result = a>b ? ["firstNumber", a] : ["secondNumber", b];
   var result = (
      a>b ? ["firstNumber", a] : ["secondNumber", b]
   );

Undeclared ā€˜firstNumber’.

That should be declared properly using var or const. As you’re using var in your code I’ll remain consistent with that.

// firstNumber = 125
var firstNumber = 125

Expected ā€˜;’ and instead saw ā€˜secondNumber’.

Statements should be consistently ended with a semicolon.

// var firstNumber = 125
var firstNumber = 125;

Undeclared ā€˜secondNumber’.

We’ll do the same as above.

// secondNumber = 17
var secondNumber = 17;

Undeclared ā€˜console’.

That’s fine, console is short for window.console, but instead of changing console to window.console I’ll make a rare exception in regard to console and add a declaration at the top that console is allowed as a global variable.

/*jslint browser */
/*global console */
...

Line is longer than 80 characters.

// console.log(numberResult[1] + " is larger. Therefore, the bigger number is " + numberResult[0]);
console.log(
    numberResult[1] + " is larger. " +
    "Therefore, the bigger number is " + numberResult[0]
);

Expected one space between ā€˜,’ and ā€˜b’.

Now that we’re on to formatting issues, most of them are easily resolved by passing the code through jsBeautifer.

/*jslint browser */
/*global console */
function theNumber(a, b) {
    var result = (
        a > b ? ["firstNumber", a] : ["secondNumber", b]
    );
    return result;
}

var firstNumber = 125;
var secondNumber = 17;

var numberResult = theNumber(firstNumber, secondNumber);

console.log(firstNumber);
console.log(secondNumber);
console.log(
    numberResult[1] + " is larger. " +
    "Therefore, the bigger number is " + numberResult[0]
);

Expected ā€˜?’ at column 8, not column 14.

Ternary statements should have their different parts made more easily visible.

    // var result = (
    //     a > b ? ["firstNumber", a] : ["secondNumber", b]
    // );
    var result = (
        a > b
        ? ["firstNumber", a]
        : ["secondNumber", b]
    );

And JSLint is finally satisfied.

No, the function is not comparing anything about the arrays.

Instead, it’s comparing a and b, and depending on which one is larger, the function is returning one array or another.

The code will be easier to understand when it is as an if statement instead.

    // var result = (
    //     a > b
    //     ? ["firstNumber", a]
    //     : ["secondNumber", b]
    // );
    // return result;
    var result;
    if (a > b) {
        result = ["firstNumber", a];
    } else {
        result = ["secondNumber", b];
    }

And now it’s easier to see that the result value is being returned from the function, no matter the result of the if statement. We can do without the result variable completely and just return the array.

    // var result;
    // if (a > b) {
    //     result = ["firstNumber", a];
    // } else {
    //     result = ["secondNumber", b];
    // }
    if (a > b) {
        return ["firstNumber", a];
    } else {
        return ["secondNumber", b];
    }

Even though anonymous functions are possible, you should always name your functions so that you and/or other people reading the code have an easier time understanding what is going on.

1 Like

ā€œIt’s much easier to accept critique from an inhuman machine, than from someone elseā€

Haha, no worries, thanks for your time.

I am getting the idea that breaking lines is good, rather than letting things stay as a long line. You said, ā€œLine is longer than 80 characters.ā€ Is that the normal way to break for readability, every 80 characters?

I liked the new ternary statement. Rather than assign a variable, THEN the condition after the semicolon, I can simply assign the conditional directly to the variable with an ā€œ=ā€ operator. Nice.

So it looks like I forgot to assign the firstNumber and secondNumber as a variable in the second code exercise. It still worked, and is that because the browser assumed what I was trying to do so that the code wouldn’t break?

"No, the function is not comparing anything about the arrays.

Instead, it’s comparing a and b, and depending on which one is larger, the function is returning one array or another."

Ah ha, I see that now.

So, one thing I was wondering about functions is whether there is agreement in the field about anonymous functions vs named. Is there never a reason to use anonymous, and can any script using an anonymous function be written with a named one and still get the job done? Personally I do prefer naming them.

1 Like

Yeah, I’m actually going to take an ECMA course after my beginner JS course. The instructor explained the difference between var and let, that ā€œletā€ has a smaller scope than ā€œvarā€ and it seemed to me that, if it doesn’t do any harm, I could just use ā€œletā€ in that case.

Bit of A, bit of B. Mostly personal preference i think, and highly situational; though someone may have a statistical or logical reasoning for one over the other.

An anonymous function, for me, is most often used inline of something i’m trying to do exactly once in my code.

Consider the following:

ā€œI want to filter this array of objects by their name element - I want to find all the objects whose name starts with K.ā€

Rather specific function, and one that i’m only going to use once.

I COULD define a named function:

function findTheKs(a) {
   return a.name.charAt(0) == "K";
}

let kobjs = myobjs.filter(findtheKs); 

or, i could inline the function anonymously:

let kobjs = myobjs.filter((a) => a.name.charAt(0) == "K");

The same way that you don’t HAVE to declare your parameters independantly;

let a = 4
let b = 5
console.log(a+b)

Is 'anonymous’ly defined as

console.log(4+5)

… the only difference is that with the first one, i can reuse my named thing.

The compromise is to define the arrow-notation function too, for improved readability.

let findTheKs = (a) => a.name.charAt(0) === "K";
let kobjs = myobjs.filter(findTheKs);

Indeed, you could write the named function as an arrow function. The primary factor for me in these cases is ā€œAm i going to use this more than once? If so, i’m going to define it. Otherwise, i’ll probably inline it.ā€

Also out of habit, I refer to these as lambda functions, rather than ā€˜anonymous’. Strictly speaking, a lambda function is a special kind of anonymous function, but you may hear the terms being used somewhat interchangably.

The main benefit of defining the arrow-function as a variable name is not only for programmer readability.

let findTheKs = (a) => a.name.charAt(0) === "K";

The other main benefit is that browsers don’t treat it as an anonymous function and know to use the findTheKs variable name for the function name when it appears in the call stack while debugging, making it easier for you to understand what’s going on.

2 Likes

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.