Chapter 3 Functions has the following code snippet:
const power = function(base, exponent) {
let result = 1;
for(let count = 0; count < exponent; count++) {
result *= base;
}
return result;
};
console.log(power(2, 10));
// 1024
can someone explain what is going on in the code line by line, i'm confused by let result = 1 the most. Thanks!
In the first line, you're declaring a variable result. However, it's being declared with let, not var. Let is similar to var, except it can't be accessed outside the block it is defined in (including functions, loops and conditional statements). And since it's in a function here, that first line is equivalent to:
var result = 1;
In the second line:
for (let count = 0; count < exponent; count++) {}
You're looping over exponent - so the code within the {} of the loop will be executed exponent times.
In the third line:
result *= base;
You're multiplying result and base, and assigning the value to result. This line is equivalent to:
result = result * base;
Final line:
return result;
This line stops the function and returns result. The return means that whenever a function is called, it essentially is replaced with the return value (like in this line):
console.log(power(2, 10));
This calls power() with arguments 2 and 10, and logs the returned value to the console.
This example is a simple approach of building and executing an exponential function in JavaScript.
That said, we know that the below will essentially be creating something like the following in pseudocode:
print the result of (number to the power of some other number)
The code walkthrough:
// initialize a constant variable named 'power' as a function declaration with two arguments, 'base' and 'exponent' which will be used inside the function
const power = function(base, exponent) {
// declare and initialize variable called 'result' and set it with value of 1
// why this is 1, is because any number to the power of 1 is itself, so rather than setting this to 0, this must be 1 to ensure that the exponential function works accurately
let result = 1;
// let count = 0; this will initialize a variable named count to be used within the loop
// count < exponent; this is the conditional statement, it means that the loop will continue looping until the condition is met, meaning loop until 'count' is no longer less than 'exponent'
// count++; this increments the value of the initial variable, in this case 'count' for every trip through the loop for the duration that the condition statement remains true
for (let count = 0; count < exponent; count++) {
// multiply the 'result' variable by the 'base' variable and set it as the new value of the 'result' variable
result *= base;
}
// return the 'result' variable so that it is now available outside of the function
return result;
};
// pass in the 'base' and 'exponent' arguments for the function 'power' in order to get the value (effectively, 2^10), and then print this value to the console
console.log(power(2, 10));
// 1024
Related
I'm trying to wrap my head around the return statement but I can't see a reason why I should use one. My code works just fine without using one...
In both examples my console prints out 10 not matter if I use return or not.
Without return:
var sum = 5;
function myFunction() {
sum += 5;
}
myFunction();
console.log(sum);
With return:
var sum = 5;
function myFunction() {
return sum += 5;
}
myFunction();
console.log(sum);
By default, functions return the value undefined. If you want the function to return some other value, you need to have a return statement.
You may also use a return statement to halt execution of the function based on some logic, again returning a value that has some meaning or just undefined.
In the first example in the OP, the function is called and the return value is not used for anything, so it doesn't matter what the return value is and a return statement isn't necessary.
In another scenario, the return value might be important, e.g. a function that generates an integer random number between 0 and 10:
function getRandomInteger(){
return Math.floor(Math.random() * 11);
}
function showRandomNumber() {
document.getElementById('s0').textContent = getRandomInteger();
}
<button onclick="showRandomNumber()">Show random number</button>
<span id="s0"></span>
In the above, the getRandomInteger function needs to return a specific value, so it uses a return statement. The showRandomNumber function just displays the random number, so it doesn't need a return statement as the caller (the listener on the button) doesn't care what the return value is.
Here is what is happening with your example:
var sum = 5; //Sets the sum to =5
function myFunction() {
return sum += 5; // += reassigns the global (sum) to 10
}
myFunction();
console.log(sum);
A better example would be this:
sum = 5;
function myFunction() {
var sumOther = sum + 5;
return sumOther;
}
console.log(“sum:” + sum); // 5
console.log(“myFunction:” + myFunction()); // 10
This is how you would get the run of the function and not the global variable ‘sum’
This is because you use (global) variable declared outside the function (function modify it directly so there is no need to return value). However it is not good way of write functions because they are less reusable because they need proper global context to be used. Better is to use something like this:
function myFunction(num) {
return num += 5;
}
var sum = 5;
var result = myFunction(5) ;
console.log(result); // -> 10
this function can be easily used ind different context because it have parameter num and works only on it (function uses only values declared inside its declaration and body)
The trick in your case a is scope of a function. In both cases variable sum is defined in global scope. When you calling the function, it goes through the following steps:
Look whether var sum is defined in current step Since it not defined
inside the function, go one step over and take a look into outer
scope. Yes, it is defined here, start using it.
Perform calculation.
You are using incremental operator sum += 5 so actually it can be
written as sum = sum + 5. If you will look into second case,
you'll notice that variable have increased value now. And since that
variable is taken from global scope, your function just mutates it.
NOTE: At this point no matter whether you are returning something
from function or not. Your function just mutated outer variable.
The last step - exit from function. As I said earlier, return value
matters only if you want to use result of function call directly,
for instance: var result = myFunction()
I had this task: "Use the rest parameter to create an average() function that calculates the average of an unlimited amount of numbers". And wen I ran this code, I have 0 answer.
function average(...nums) {
let total = 0;
for (const num of nums) {
total += num;
len = nums.length;
}
total = total/len;
return total;
}
console.log(average());
But why? Why when I divide by the undeclared variable 0 the answer is 0 and not NaN? It's NaN if I run the following code (with declared variable).
function average(...nums) {
let total = 0,
len;
for (const num of nums) {
total += num;
len = nums.length;
}
total = total / len;
return total;
}
console.log(average());
P.s. the right answer in the task is 0.
The reason this happens is that in loose mode (i.e. not strict mode), assigning to undeclared variables makes them global.
So you run average() once with some arguments, which sets the global len to whatever number, and returns the correct average. (This is also why the udacity tests pass, the order of the tests matter. If they had run the empty input test first, it would have failed)
You then run it again with no arguments, since setting len happens inside the loop, it doesn't happen again because a for..of loop over an empty array doesn't even enter, so then the result of 0 (the sum) divided by whatever (the previous len, set to any number) will be 0.
If you had run it in strict mode, you would have gotten an error about assigning to undeclared variables, even when you run it with arguments.
This is why you always:
Use strict mode (add 'use strict' to your top level function or file, if you use webpack or a similar bundler, you have this by default)
Declare your variables.
A correct version of this, assuming they want an empty input to return 0, is as follows:
function average(...nums) {
'use strict'; // enter strict mode
if (nums.length === 0) { return 0; }
let total = 0;
for (const num of nums) {
total += num;
}
return total / nums.length;
}
console.log(average());
You must directly define the behavior for empty input, because strictly speaking, the average of a set of 0 numbers is undefined.
I need to find the sum of integers in an array using recursion.
The following code throws an error :
var sum = function(array) {
if(array.length === 0) return 0;
while(array.length) {
sum = array[0] + sum(array.slice(1));
return sum;
}
}
while this works :
var sum = function(array) {
if(array.length === 0) return 0;
while(array.length) {
return array[0] + sum(array.slice(1));
}
}
The difference is the way the sum is returned. Can someone explain?
As mentioned in comments, the while loop never loops - it executes a return statement before testing the loop condition a second time.
Even so, why does the first version work the first time it is called but not the second?
sum = array[0] + sum(array.slice(1));
stores the right hand expression value in sum, after the function call to sum returns. That variable is in scope, so the assignment is valid.
But the assignment doesn't occur until after the call to sum (on the right hand side) returns. Each time sum returns, assignment overwrites the variable sum with the partial, and eventually the final result.
So the first call works successfully, but leaves sum set to the result of the first call. Since you can't call a number, it errors the second time you call it.
Can someone please explain how this gets 50, and how does the algorithm works. Thanks.
var multipliers = function makeMultipliers (max) {
var result = [];
for (var i = 0; i < max; i++)
result.push (function (x) {return x * i;});
return result;
}
multipliers(10) [2] (5)
???
what’s the value?
50, not 5
can you fix it?
Source: http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-170-software-studio-spring-2013/lecture-notes/MIT6_170S13_35-java-fn-cls.pdf
page 30
It's a scope issue. By the time the last function is called, i is where it was last seen at that scope last which would be 10. You can prevent this with a closure.
function multipliers(max){
var a = [];
for(var i=0; i<max; i++){
(function(i){
a.push(function(x){return x*i});
})(i);
}
return a;
}
In this case, the closure is a self-executing function that scopes off i at each step of the loop. If this did not happen the scope would go to the multipliers function itself. Since the loop has already completed by the time you are calling the function which you pass 5 to, which happens to be at step 2 of the Array that multipliers returns, i has already reached 10. Obviously, 10*5 is 50. When the closure is used is last position is 2 within the scope it is in, giving you the result that is sought. 5*2 = 10.
console.log(multipliers(10)[2](5));
This code creates an array of functions which will incorrectly all end up referring to the final value of i, but which are intended to freeze the value of i during each iteration.
To fix it you simply could add a level of locality to the iteration variable by embedding a new local variable that freezes the value of i within another function. For example, below the existing local variable i is passed into the dummy function as an argument, and the value of i at that instant is frozen into the new local variable i which is independent of the original i and not changed by the subsequent iterations of the original i.
result.push (function (x) {return x * i;})
result.push((function(i) {
return function (x) {return x * i;};
})(i));
var avg = function()
{
var sum = 0;
for (var i = 0, j = arguments.length; i < j; i++)
{
sum += arguments[i];
}
return sum / arguments.length;
}
When I try to call this like:
var average = avg(2,3,5);
average; // It works fine;
But how do I call it without assigning to a variable?
If anybody can give any suggestion it will be delightful..Thanks.
You'd simply call it like this:
avg(2, 3, 5);
If you want to see the result, put it in an alert call:
alert( avg(2, 3, 5) );
You don't need to put the result from calling the function in a variable, you can do whatever you like with it.
For example, use it as the value in an alert:
alert(avg(2,3,5));
You can use it in another expression:
var message = "The average is " + avg(2,3,5);
You can use it directly in another call:
someFunction(avg(2,3,5));
You can even throw the result away by not doing anything with it, even if that's not useful in this specific situation:
avg(2,3,5);
If you don't put the result into a variable or in a compatible context, this function cannot output anything, which makes it difficult to use unless you make it output the result. Try this :
var avg = function()
{
var sum = 0;
for (var i = 0, j = arguments.length; i < j; i++)
{
sum += arguments[i];
}
var retvalue = sum / arguments.length;
consoloe.log("avg: "+retvalue);
return retvalue ;
}
Then it may help you to see whenever the function is called or not.
You need to understand the concept of expressions.
Every expression as a whole represents one value. An expression can be made up of multiple subexpressions that are combined in some manner (for example with operators) to yield a new value.
For instance:
3 is an expression (a literal, to be specific) that denotes the numeric value three.
3 + 4 is an expression, made up of two literal expressions, that as a whole yields the value 7
When you assign a value to a variable – as in var average = – the right hand side of the =-operator needs to be an expression, i.e. something that yields a value.
As you have observed, average will have been assigned the value five. It thus follows, that avg(2, 3, 5) must itself be an expression that evaluated to the value 5.
average itself is an expression, denoting the current value of said variable.
The most important thing to take away from this is, that avg() is in no way connected to var average =. avg() stands on its own, you can just think it like an ordinary value such as 5 (there are other differences of course).
If you have understood the concept of expressions and values, it should be clear that if you can do
var average = avg(2,3,5);
average; // It works fine;
You can also do
avg(2,3,5);