/    Sign up×
Community /Pin to ProfileBookmark

function issue

Hi all

I have the following function:
`function finalGrade(num1, num2, num3) {
if ((num1 < 0 || num1 > 100) || (num2 < 0 || num2 > 100) || (num3 < 0 || num3 > 100)) {
return ‘You have entered an invalid grade’;
} else {
const average = ((num1 + num2 + num3) / 3);
}
if (average <= 59) {
return ‘F’;
} else if (average <= 69) {
return ‘D’;
} else if (average <= 79) {
return ‘C’;
} else if (average <= 89) {
return ‘B’;
} else if (average <= 100) {
return ‘A’
}
};
console.log(finalGrade(50, 100, 60));`

But this code for some reason that I cant figure it out its not working, could anyone give me a hand…πŸ™‚

to post a comment
JavaScript

11 Comments(s) ↴

Copy linkTweet thisAlerts:
@KeverOct 03.2020 β€”Β Constants are block scoped, so the constant 'average' isn't available outside it's else-block. Change it to a variable instead.
Copy linkTweet thisAlerts:
@NachfolgerOct 03.2020 β€”Β What ^ they said, and you should also return after indicating that the inputs are invalid, else the function will continue.
Copy linkTweet thisAlerts:
@nigh-knightOct 08.2020 β€”Β Const is a block scope variable, meaning it lives in the block (the block is defined by the curly brackets of the else statement), because of this it's not able to be read in the other blocks - if statements, defined.

To get around this simply rename it to var

Here's the scope of variables in javascript:

var:global scope(able to be used anywhere in the code)

let:block scope
Copy linkTweet thisAlerts:
@SempervivumOct 08.2020 β€”Β var:global scope(able to be used anywhere in the code)[/quote]
??? Try this code:
function someFunc() {
var someVar = 124;
}
someFunc();
console.log(someVar);
Copy linkTweet thisAlerts:
@rpg2009Oct 08.2020 β€”Β You don't need that else block. If the numbers aren't valid the function returns early. Therefore no need for 'var'

``<i>
</i>function finalGrade (num1, num2, num3) {
if ((num1 &lt; 0 || num1 &gt; 100) || (num2 &lt; 0 || num2 &gt; 100) || (num3 &lt; 0 || num3 &gt; 100)) {
return 'You have entered an invalid grade'
}
// will only get to here if the numbers are valid
const average = ((num1 + num2 + num3) / 3)

if (average &lt;= 59) {
return 'F'
} else if (average &lt;= 69) {
return 'D'
} else if (average &lt;= 79) {
return 'C'
} else if (average &lt;= 89) {
return 'B'
} else if (average &lt;= 100) {
return 'A'
}
}<i>
</i>
``
Copy linkTweet thisAlerts:
@nigh-knightOct 08.2020 β€”Β @Sempervivum#1624053

var is also function scope meaning it lives in the scope of the function

every variable is function scope,

only var is global scope

only let and const are block scope

only const can be reassigned
Copy linkTweet thisAlerts:
@rpg2009Oct 09.2020 β€”Β My understanding.

var is only global if it is defined in the global namespace. var is lexically scoped.

if you want to define a global that's nested within a function you can take off the var

e.g.
``<i>
</i>function bar() {
myGlobal = 5
}

bar()

console.log(myGlobal) // 5<i>
</i>
`</CODE>
standard practice though would be to define your global on window

e.g.
<CODE>
`<i>
</i>(function(){
const myApp = // ... code here
window.myApp = myApp // exposed to the global namespace
}())<i>
</i>
`</CODE>
When a function is invoked/executed the var variables are hoisted to the top and are initially assigned a value of 'undefined'

The variable is only assigned a value, when the function execution reaches that variable declaration. The same can be said in the global namespace e.g.

<CODE>
`<i>
</i>console.log(x) // undefined

var x = 5

console.log(x) // 5<i>
</i>
`</CODE>
As mentioned var is lexically scoped, which means in the case of a function invocation, if you try to use a variable that hasn't been defined inside that function it will look up the scope chain to a wrapping parent functions to find it, if it is not found there then to the next parent all the way up to the global namespace

<CODE>
`<i>
</i>function parent() {
var x = 5

function child() {
// will not be able to find x in child so looks up the scope chain to parent
console.log(x)
}

child()
}

parent() // 5<i>
</i>
`</CODE>
or
<CODE>
`<i>
</i>var x = 10 // defined in the global namespace

function parent() {
// x isn't found here so looks up the scope chain to the global namespace

function child() {
// will not be able to find x in child so looks up the scope chain to parent
console.log(x)
}

child()
}

parent() // 10<i>
</i>
`</CODE>

<QUOTE><i>&gt; </i><POSTMENTION discussionid="391478" displayname="nigh-knight" id="1624080" number="7" username="nigh-knight">@nigh-knight#1624080</POSTMENTION> only const can be reassigned</QUOTE>

Will take that as a typo, it <STRONG>**can't**</STRONG> be reassigned. However in the case of an object type it can still be mutated e.g.

<CODE>
`<i>
</i>const myArray = [1,2,3]

myArray.push(4) // [1,2,3,4]<i>
</i>
`</CODE>
There is another distinct difference, <STRONG>**let**</STRONG> and <STRONG>**const**</STRONG> cannot be used ahead of their definition and will throw an error

<CODE>
`<i>
</i>console.log(x) // Uncaught ReferenceError: x is not defined

let x = 5 <i>
</i>
`</CODE>
As you see above with var and 'undefined' that isn't the case.

Edit: What has just dawned on me and where we are maybe getting crossed wires, is that var is not block scoped like const and let. e.g.

<CODE>
`<i>
</i>var x = 5

if (x === 5) {
var y = 10
}

console.log(y) // 10<i>
</i>
``

That doesn't make it global though

Just to finish off β€” outside of a bit of experimentation in snippets β€” I am not quite sure why you need var now. I saw it in a piece of code recently mixed with const and let and just presumed the person had copied a section of code from a dated source. If you want access outside of the block, then why not define it just before that block? Maybe I am missing something
Copy linkTweet thisAlerts:
@JMRKEROct 11.2020 β€”Β This made more sense to me.

Does entry validity checks prior to trying to determining grade.

No nested 'if ... else' statements.

&lt;script&gt;<br/>
function finalGrade (num1, num2, num3) {

function isOutOfRange(num) {<br/>
let flag = isNaN(num); // true if undefined entry<br/>
if ((num &lt; 0 | num &gt; 100)) { flag = true; } // out of range entry<br/>
return flag;<br/>
}

if (isOutOfRange(num1) | isOutOfRange(num2) | isOutOfRange(num3)) {<br/>
return 'You have entered an invalid grade'<br/>
}<br/>
// will only get to here if the numbers are valid<br/>
const average = ((1<EM>*num1 + 1*</EM>num2 + 1*num3) / 3) // any str numbers to numbers

if (average &lt; 60) { return 'F'; } // does not round up from 59 to 60<br/>
if (average &lt; 70) { return 'D'; }<br/>
if (average &lt; 80) { return 'C'; }<br/>
if (average &lt; 90) { return 'B'; }<br/>
return 'A'; // all checks made of grade<br/>
}


// test actions<br/>
alert(finalGrade(70,70,70)); // valid C<br/>
alert(finalGrade(70,-70,70)); // invalid entry<br/>
alert(finalGrade('70','70','70')); // valid C<br/>
alert(finalGrade(70,'C',70)); // invalid entry<br/>
alert(finalGrade(69,70,71)); // valid C

alert(finalGrade(59,60,60)); // F<br/>
alert(finalGrade(69,70,70)); // D<br/>
alert(finalGrade(79,80,80)); // C<br/>
alert(finalGrade(89,90,90)); // B<br/>
alert(finalGrade(99,100,100)); // A<br/>
&lt;/script&gt;


For some reason the average calculation is losing the multipliers.

Use this instead

// will only get to here if the numbers are valid<br/>
const average = ((num1*1 + num2*1 + num3*1) / 3) // any str numbers to numbers
Copy linkTweet thisAlerts:
@rpg2009Oct 12.2020 β€”Β Just playing with an es6 approach :)

Both valid scores and average could be extracted into helper functions
``<i>
</i>// every will return false if any scores fail the test
function validScores (...scores) {
return scores.every(score =&gt; score &gt;= 0 &amp;&amp; score &lt;= 100)
}

// using rest parameters e.g. (...nums) any number of
// arguments are converted to an array
function average (...nums) {
return nums.reduce((x, y) =&gt; x + y) / nums.length
}

function finalGrade (grades = [], score1, score2, score3) {

// if !not valid scores return
if (!validScores(score1, score2, score3)) {
return 'You have entered an invalid score'
}

const averageScore = average(score1, score2, score3)

...
}<i>
</i>
``
Copy linkTweet thisAlerts:
@JMRKEROct 12.2020 β€”Β Just playing around now.

I wanted to add the following:
  • 1. Ability to enter and average more or less than 3 grades.

  • 2. Ability to compute and display the average value.

  • 3. Tired of display with alerts, so changed to write to screen (optional test action)


  • So I came up with this program modification

    &lt;!DOCTYPE html&gt;&lt;html lang="en"&gt;&lt;head&gt;<br/>
    &lt;meta charset="UTF-8"&gt;<br/>
    &lt;meta name="viewport" content="width=device-width,initial-scale=1.0, user-scalable=yes"/&gt;<br/>
    &lt;title&gt; Test Page &lt;/title&gt;<br/>
    &lt;!-- From: <URL url="https://www.webdeveloper.com/d/391478-function-issue/9">https://www.webdeveloper.com/d/391478-function-issue/9</URL> --&gt;<br/>
    &lt;/head&gt;&lt;body&gt;

    &lt;pre id='demo'&gt;&lt;/pre&gt;

    &lt;script&gt;<br/>
    console.clear();

    function finalGrade () {

    function isOutOfRange(num) {<br/>
    let flag = isNaN(num); // true if undefined entry<br/>
    if ((num &lt; 0 | num &gt; 100)) { flag = true; } // out of range entry<br/>
    return flag;<br/>
    }

    // arguments is part of all functions<br/>
    var nums = [...arguments], sum = 0, err = false;<br/>
    for (let i=0; i&lt;nums.length; i++) {<br/>
    if (isOutOfRange(nums<I>[i])) { err = 'You have entered an invalid grade' }<br/>
    else { sum += nums<I>[i]*1; } // summation in same loop<br/>
    }<br/>
    if (err) { return err; } // input error found<br/>
    <br/>
    const average = (sum / nums.length);<br/>
    let grade = 'A';<br/>
    if (average &lt; 90) { grade = 'B'; } // does not round up from 59 to 60<br/>
    if (average &lt; 80) { grade = 'C'; }<br/>
    if (average &lt; 70) { grade = 'D'; }<br/>
    if (average &lt; 60) { grade = 'F'; }<br/>
    <br/>
    var result = [];<br/>
    result.push(grade,average.toFixed(1)); // all checks made of grade<br/>
    return result;<br/>
    }<br/>
    <br/>
    // test actions - can get letter grade with [0] or average grade with [1]<br/>
    document.getElementById('demo').append(finalGrade(70,70,70)+'n'); // valid C<br/>
    document.getElementById('demo').append(finalGrade(70,-70,70)+'n'); // invalid entry<br/>
    document.getElementById('demo').append(finalGrade('70','70','70')+'n'); // valid C<br/>
    document.getElementById('demo').append(finalGrade(70,'C',70)+'n'); // invalid entry<br/>
    document.getElementById('demo').append(finalGrade(69,70,71)+'n'); // valid C<br/>
    <br/>
    document.getElementById('demo').append(finalGrade(59,60,60,60,60,60,60)+'n'); // F<br/>
    document.getElementById('demo').append(finalGrade(69,70,70,70,70,70,70)+'n'); // D<br/>
    document.getElementById('demo').append(finalGrade(79,80,80,80,80,80,80)+'n'); // C<br/>
    document.getElementById('demo').append(finalGrade(89,90,90,90,90,90,90)+'n'); // B<br/>
    document.getElementById('demo').append(finalGrade(99,100,100,100,100,100,100)+'n'); // A<br/>
    <br/>
    document.getElementById('demo').append(finalGrade(70,80,90,100,75,85,95)+'n'); <br/>
    <br/>
    &lt;/script&gt;<br/>
    &lt;/body&gt;&lt;/html&gt;<br/>


    Might want to add checks for no entries made so division by zero is eliminated.

    Copy linkTweet thisAlerts:
    @rpg2009Oct 12.2020 β€”Β Not thoroughly tested
    ```
    // every will return false if any scores fail the test
    function validScores (scores) {
    return scores.every(score => score >= 0 && score <= 100)
    }

    function average (nums) {
    return nums.reduce((x, y) => x + y) / nums.length
    }

    function finalGrade (grades = [], ...scores) {

    // if !not valid scores return
    if (!validScores(scores)) {
    return 'You have entered an invalid grade'
    }

    const averageScore = average(scores)

    // using destructuring to get the indexed values
    // e.g. [grade, score] = ['B', 80] -> grade = 'B' score = 80
    const [grade] = grades.find(([grade, score]) => averageScore >= score)

    return grade
    }

    // could have used Map possibly
    const grades = [['A', 90], ['B', 80], ['C', 70], ['D', 60], ['F', 0]]

    console.log(finalGrade(grades, 59, 60, 60, 50)) // F
    console.log(finalGrade(grades, 69, 70, 70)) // D
    console.log(finalGrade(grades, -79, 80, 80)) // You have entered an invalid grade
    console.log(finalGrade(grades, 89, 90, 90, 75, 60)) // B
    console.log(finalGrade(grades, 99, 100, 100)) // A
    Γ—

    Success!

    Help @fretagi spread the word by sharing this article on Twitter...

    Tweet This
    Sign in
    Forgot password?
    Sign in with TwitchSign in with GithubCreate Account
    about: ({
    version: 0.1.9 β€” BETA 4.19,
    whats_new: community page,
    up_next: more Davinciβ€’003 tasks,
    coming_soon: events calendar,
    social: @webDeveloperHQ
    });

    legal: ({
    terms: of use,
    privacy: policy
    });
    changelog: (
    version: 0.1.9,
    notes: added community page

    version: 0.1.8,
    notes: added Davinciβ€’003

    version: 0.1.7,
    notes: upvote answers to bounties

    version: 0.1.6,
    notes: article editor refresh
    )...
    recent_tips: (
    tipper: @Yussuf4331,
    tipped: article
    amount: 1000 SATS,

    tipper: @darkwebsites540,
    tipped: article
    amount: 10 SATS,

    tipper: @Samric24,
    tipped: article
    amount: 1000 SATS,
    )...