Related
I have this problem on freeCodeCamp as I'm learning JavaScript.
I'm trying to understand this block of code.
function multiply(arr, n) {
if (n <= 0) {
return 1;
} else {
return multiply(arr, n-1)*arr[n-1];
}
}console.log(multiply([2,2,4],3));
As a whole, I understand what this code above does. But not this line below.
multiply(arr, n-1)*arr[n-1];
There's already a about post this specific problem here, but I have read all of the comments and I did not understand.
What I don't understand specifically is (arr, n-1). Exactly what does that do? The rest of the line I can understand after a long time thinking, it's just that little piece that I can't make sense of.
What I don't understand specifically is "(arr, n-1)". Exactly what does that do?
This is the argument list for the function call of the multiply() function. You cannot understand this in isolation because it belongs to the function call.
In other words, the syntactic element is not (arr, n-1), it is multiply(arr, n-1).
A parameter is kind of like a "hole" that you leave in a function definition. Parameters allow you to make functions re-usable in different contexts.
For example, a function like this:
function doubleTheValueSix() {
return 2 * 6;
}
is not very useful because it can be used for only one very specific thing. However, we can make it more useful by parameterizing it:
function doubleAnyArbitraryValue(n) {
return 2 * n;
}
is much more useful. Here, n is called the parameter and (n) is called the parameter List. In this case, there is only one parameter in the parameter list, but there can be arbitrary many, including – as we have seen above – zero.
An argument is what you pass to a function call to "fill in" the "hole" left by the parameter in the function definition.
So, in this code here:
doubleAnyArbitraryValue(42)
The literal 42 is the argument which gets bound to the parameter n inside the function body of doubleAnyArbitraryValue. In other words, everywhere n appears in the function body, it gets replaced with 42.
So, in this case, 42 is the argument and (42) is the argument list.
What this means in your particular code snippet is the following:
Look up the name multiply in the local scope. It could be a function defined in the local scope (or in an enclosing scope), a const, a let, or a var defined in the local scope (or in an enclosing scope).
Call the object you found in step #1, passing the result of evaluating the expressions in the argument list as arguments:
Evaluate the expression arr (which essentially means: look up the name arr in the local scope; it could be a const, a let, or a var defined in the local scope (or in an enclosing scope)).
Evaluate the expression n-1:
Look up the name n in the local scope; it could be a const, a let, or a var defined in the local scope (or in an enclosing scope).
Apply the Binary Arithmetic Subtraction Operator - to the result of step 2.1.1 and the Numeric Literal 1.
You can find the details about how function calls work in subsection 13.3.6 Function Calls of the ECMAScript Language Specification. (Note, the version I linked to is the Living Document which always shows the current state of the next release, but that doesn't matter in this case – how function calls work fundamentally hasn't changed since ECMAScript was still called LiveScript in 1995 and even before that when it was still called Mocha.)
I have learned in "Function section" of the Javascript course in Codecademy that: to call a function, we have to use 'return' keyword inside the function. But in the "Array section" of the Javascript course found a function can be called without using 'return' keyword inside that function. Can anyone explain when I must use 'return' keyword inside the function and when it is optional?
I am attaching the code snippet for Your reference.
const flowers = ['peony', 'daffodil', 'marigold'];
function addFlower(arr) {
arr.push('lily');
}
addFlower(flowers);
It is not necessary that function must return any value.
When you not required anything from the function then you don't require to return anything. This function called void function.
If you require some value from function the you must return it.
The return keyword is used only to get back some value from the function to the caller so that the value can be used later. In case, if you don't want to use any value from the function, you can omit the return statement.
In the case of objects as a parameter, if that object itself is changed, then it will change the original copy which was passed as well. So, at that time also, no need to return that object from the function.
With the return statement you actually return a value to the caller. For example:
function add(a, b) {
return a+b;
}
var c = add(5,7);
If you have a function that just performs a task without a return value you do not use the keyword. E.g.:
function sayHello() {
console.log('Hello');
}
sayHello();
Note: A return statement ends the function; statements after the return will not be executed.
In fact, there might be a need for returning a value, just like Array.prototype.push() is doing it. Please see the documentation of MDN Web Docs.
function addOneFlower(flowers) {
const newFlower = "Bellflowers";
return flowers.push(newFlower);
}
const flowerArr = [];
let sizeOfFlowerArr = addOneFlower(flowerArr);
// sizeOfFlowerArr starts with 1
sizeOfFlowerArr = addOneFlower(flowerArr);
// sizeOfFlowerArr increased to 2
Use return when you might want to transfer information from inside the function directly to the caller. For example, maybe a caller of addFlower would want to know the name of the flower that was added. Then you would probably have something like
const addedFlower = addFlower(flowers);
This assigns the return value of addFlower to the addedFlower variable. But for that to work, addFlower should return something, eg:
function addFlower(arr) {
arr.push('lily');
return 'lily';
}
If you don't ever need to transfer information directly from inside the function to the caller, then all invocations of the function should be in a standalone line, like
addFlower(flowers);
and there's no need (or sense) for addFlower to return anything.
Note that the caller may sometimes want information that the function returns, but sometimes a caller may not care about it. But the function may not know which, so it should return regardless, and the caller of the function can use the resulting expression if it wants, or the caller can ignore it. Eg, in the same script, there might be one line like
const addedFlower = addFlower(flowers);
and another like
addFlower(flowers); // Don't care about the return value
In this case, addFlower should be returning something regardless, leaving it completely up the caller to do something with the result.
The function when called will run till it reaches a return statement, or the end. If you are using a function with return value, you need to have a return statement in your function definition.
But if you are using a function with no return statement and it can run till the end of the function, than you don't have to have a return statement in the function definition. For example:
function helloWorld() {
console.log('Hello World');
}
the simple example I can give you is this.
let say you have some unknown numbers you want to calculate when the user gives you an input.
for example, you ask your users when he/she was born to calculate his/her age.
function calcAge(yearBorn){
var age = 2019 - yearBorn;
return 'hello user your age is ' + age;
}
calcAge(1993);
when the user gives you the year she/he was born, it will be passed to the yearBorn parameter and will be calculated against the current year. but to use it, you should return it. if you don't return it you will get 'undefined', when you call the function. You have probably seen the console.log() function previously. it is used only on the dev tool in the browser for development purposes. if you want to use the end result from that function, you should use the return keyword then you will get the calculated age instead of 'undefined'! this has something to do with function scope. if you declare the age variable outside of the function and reassign it again in the function, you can probably use the age without the return statement like below.
var age2;
function calcAge2(yearBorn){
age2 = 2019 - yearBorn;
}
When you call it, since the age2 is declared outside of the function, you will be able to access it from the global scope. even if you didn't return it, the function call will update the age2 variable based on the calculation. but declaring a variable in the global scope is not a good practice.
in your example, you have already declared the variable outside of your function.
with const flowers = ['peony', 'daffodil', 'marigold'], you are only pushing additional items in your array by calling the function. if you had declared your flowers array inside the function like bellow, though it is not the best example
function addFlower() {
const flowers = ['peony', 'daffodil', 'marigold'];
flowers.push('lily');
return flowers;
}
then you have to use the return statement to return the value of the array to use it later.
in your case, you are just adding the items in your pre-existing array that was declared in the outer scope.
you don't have to use return if your intention is not to return the value from the function local scope.
since you declared your variable outside of the function, you can update those values without a return statement like you did. but if you want to return a value from a function to be used, you should use the return statement.
check the two examples below. copy them and play around with them in the console.
On the first one since I declared the variable sum inside the function (in the local scop), I have to use the return statement to get the value that is calculated when I call the function. otherwise, the function call will give me undefined value;
function add(x, y){
let sum = x + y;
return sum;
}
but on the second one, the sum variable is declared outside of the function in the global scope. all I am doing when I call the function is updating the pre-existing variable sum. because of that, I don't need to use the return statement here
let sum;
function add(x, y){
sum = x + y;
}
My advice to you, the more you learn about javascript, the dot will connect for you. just keep learning. I have been there. sometimes it feels like nothing makes sense. trust me the dots will connect as you learn more.
Simply put...
why does
setTimeout('playNote('+currentaudio.id+', '+noteTime+')', delay);
work perfectly, calling the function after the the specified delay, but
setTimeout(playNote(currentaudio.id,noteTime), delay);
calls the function playNote all at the same time?
(these setTimeout()s are in a for loop)
or, if my explanation is too hard to read, what is the difference between the two functions?
The first form that you list works, since it will evaluate a string at the end of delay. Using eval() is generally not a good idea, so you should avoid this.
The second method doesn't work, since you immediately execute a function object with the function call operator (). What ends up happening is that playNote is executed immediately if you use the form playNote(...), so nothing will happen at the end of the delay.
Instead, you have to pass an anonymous function to setTimeout, so the correct form is:
setTimeout(function() { playNote(currentaudio.id,noteTime) }, delay);
Note that you are passing setTimeout an entire function expression, so it will hold on to the anonymous function and only execute it at the end of the delay.
You can also pass setTimeout a reference, since a reference isn't executed immediately, but then you can't pass arguments:
setTimeout(playNote, delay);
Note:
For repeated events you can use setInterval() and you can set setInterval() to a variable and use the variable to stop the interval with clearInterval().
You say you use setTimeout() in a for loop. In many situations, it is better to use setTimeout() in a recursive function. This is because in a for loop, the variables used in the setTimeout() will not be the variables as they were when setTimeout() began, but the variables as they are after the delay when the function is fired.
Just use a recursive function to sidestep this entire problem.
Using recursion to deal with variable delay times:
// Set original delay
var delay = 500;
// Call the function for the first time, to begin the recursion.
playNote(xxx, yyy);
// The recursive function
function playNote(theId, theTime)
{
// Do whatever has to be done
// ...
// Have the function call itself again after a delay, if necessary
// you can modify the arguments that you use here. As an
// example I add 20 to theTime each time. You can also modify
// the delay. I add 1/2 a second to the delay each time as an example.
// You can use a condition to continue or stop the recursion
delay += 500;
if (condition)
{ setTimeout(function() { playNote(theID, theTime + 20) }, delay); }
}
Try this.
setTimeout(function() { playNote(currentaudio.id,noteTime) }, delay);
Don't use string-timeouts. It's effective an eval, which is a Bad Thing. It works because it's converting currentaudio.id and noteTime to the string representations of themselves and hiding it in the code. This only works as long as those values have toString()s that generate JavaScript literal syntax that will recreate the value, which is true for Number but not for much else.
setTimeout(playNote(currentaudio.id, noteTime), delay);
that's a function call. playNote is called immediately and the returned result of the function (probably undefined) is passed to setTimeout(), not what you want.
As other answers mention, you can use an inline function expression with a closure to reference currentaudio and noteTime:
setTimeout(function() {
playNote(currentaudio.id, noteTime);
}, delay);
However, if you're in a loop and currentaudio or noteTime is different each time around the loop, you've got the Closure Loop Problem: the same variable will be referenced in every timeout, so when they're called you'll get the same value each time, the value that was left in the variable when the loop finished earlier.
You can work around this with another closure, taking a copy of the variable's value for each iteration of the loop:
setTimeout(function() {
return function(currentaudio, noteTime) {
playNote(currentaudio.id, noteTime);
};
}(currentaudio, noteTime), delay);
but this is getting a bit ugly now. Better is Function#bind, which will partially-apply a function for you:
setTimeout(playNote.bind(window, currentaudio.id, noteTime), delay);
(window is for setting the value of this inside the function, which is a feature of bind() you don't need here.)
However this is an ECMAScript Fifth Edition feature which not all browsers support yet. So if you want to use it you have to first hack in support, eg.:
// Make ECMA262-5 Function#bind work on older browsers
//
if (!('bind' in Function.prototype)) {
Function.prototype.bind= function(owner) {
var that= this;
if (arguments.length<=1) {
return function() {
return that.apply(owner, arguments);
};
} else {
var args= Array.prototype.slice.call(arguments, 1);
return function() {
return that.apply(owner, arguments.length===0? args : args.concat(Array.prototype.slice.call(arguments)));
};
}
};
}
I literally created an account on this site to comment on Peter Ajtai's answer (currently highest voted), only to discover that you require 50 rep (whatever that is) to comment, so I'll do it as an answer since it's probably worth pointing out a couple things.
In his answer, he states the following:
You can also pass setTimeout a reference, since a reference isn't executed immediately, but then you can't pass arguments:
setTimeout(playNote, delay);
This isn't true. After giving setTimeout a function reference and delay amount, any additional arguments are parsed as arguments for the referenced function. The below would be better than wrapping a function call in a function.
setTimeout(playNote, delay, currentaudio.id, noteTime)
Always consult the docs.
That said, as Peter points out, a recursive function would be a good idea if you want to vary the delay between each playNote(), or consider using setInterval() if you want there to be the same delay between each playNote().
Also worth noting that if you want to parse the i of your for loop into a setTimeout(), you need to wrap it in a function, as detailed here.
It may help to understand when javascript executes code, and when it waits to execute something:
let foo2 = function foo(bar=baz()){ console.log(bar); return bar()}
The first thing javascript executes is the function constructor, and creates a function object. You can use either the function keyword syntax or the => syntax, and you get similar (but not identical) results.
The function just created is then assigned to the variable foo2
At this point nothing else has been run: no other functions called (neither baz nor bar, no values looked up, etc. However, the syntax has been checked inside the function.
If you were to pass foo or foo2 to setTimeout then after the timeout, it would call the function, the same as if you did foo(). (notice that no args are passed to foo. This is because setTimeout doesn't by default pass arguments, although it can, but those arguments get evaluated before the timeout expires, not when it expires.)
After foo is called, default arguments are evaluated. Since we called foo without passing arguments, the default for bar is evaluated. (This would not have happened if we passed an argument)
While evaluating the default argument for bar, first javascript looks for a variable named baz. If it finds one, it then tries to call it as a function. If that works, it saves the return value to bar.
Now the main body of the function is evaluated:
Javascript looks up the variable bar and then calls console.log with the result. This does not call bar. However, if it was instead called as bar(), then bar would run first, and then the return value of bar() would be passed to console.log instead. Notice that javascript gets the values of the arguments to a function it is calling before it calls the function, and even before it looks up the function to see if it exists and is indeed a function.
Javascript again looks up bar, and then it tries to call it as a function. If that works, the value is returned as the result of foo()
So, function bodies and default arguments are not called immediately, but everything else is. Similarly, if you do a function call (i.e. ()), then that function is executed immediately as well. However, you aren't required to call a function. Leaving off the parentheses will allow you to pass that function around and call it later. The downside of that, though, is that you can't specify the arguments you want the function to be called with. Also, javascript does everything inside the function parentheses before it calls the function or looks up the variable the function is stored in.
Because the second one you're telling it to call the playNote function first and then pass the return value from it to setTimeout.
What should be the value of final_answer in this Js code snippet and why?
function weird(x) {
var tmp = 3;
return function(y) {
return x + y + ++tmp;
}
}
var funny = weird(2);
var final_answer = funny(10);
I think value of final_answer is funny(10) because even though funny is 2+4+2 that is 8 but since that value is stored in a variable, we cannot call a variable like a function.
I don't know whether I'm correct or not.. If i'm wrong then please specify the reason why so that i can understand and not repeat this mistake.
When var funny = weird(2) is called, inside the function weird two variables are created, x with the value of 2 and tmp with the value of 3. Then a function object is created with the return statement. Code inside this function can access variables x and tmp. As this function object is then returned and assigned to variable funny which resides outside the function weird, a closure is created. This means that even though code outside of weird normally cannot access variables inside weird, the function object assigned to funny can do so.
As you call funny(10), the code calculates the sum of x with the value of 2, y with the value of 10 and the pre-incremented value 4 of tmp. So the final result is 16.
weird returns a function, which references the argument passed to weird. This is stored as funny. Calling funny (with an argument) calls the function returned from weird.
funny = weird(2);
funny(10)
>16
funny(5)
>12
funny(100)
>108
In other words, funny is the product of an anonymous function, and can be treated as though it were defined using function.
I'm trying to learn Javascript by reading Eloquent Javacript. I'm on the chapter dealing with functions and I'm stuck trying to figure out how the code below works. I don't see how the add function ever gets called. I see them calling addTwo and addFive but those names are different than add. The result of this code being run is 9. Can someone please explain this to me.
function makeAddFunction(amount) {
function add(number) {
return number + amount;
}
return add;
}
var addTwo = makeAddFunction(2);
var addFive = makeAddFunction(5);
show(addTwo(1) + addFive(1));
In makeAddFunction, a function is created, called add. This function is returned.
makeAddFunction is called twice with 2 different parameters, and stored in two variables, addTwo and addFive.
Calling addTwo() and addFive() is calling the functions created by add(), with the "amounts" 2 and 5 respectively.
addTwo(1) + addFive(1) == (1 + 2) + (1 + 5) == 9
Sometimes these types of 'closures' are called Builders, or Factories. The makeAddFunction 'builds' a special version of add based on the parameter you pass to makeAddFunction.
The addTwo function would look like:
function addTwo(number) {
return number + 2;
}
The makeAddFunction create a closure that sets amount as whatever number you pass in and returns a function that will add that amount to whatever number you pass to the new function and return it.
My best advice is you try to learn a bit about Javascript closures. Really. I might not be the answer you are looking for, but it is the best you can do if you want to understand what's happening there.
Get yourself a copy of any good javascript book. Let me suggest 'Javascript - The Good Parts' by Douglas Crockford.
For some of us, Javascript closures were not something we grokked. I hope it's easier for you.
Anyway, makeAddFunctionis a function creator. It creates new functions which are tied to the parameter you passed to makeAddFunction. Therefore, the addTwo variable receives and stores a new function, which you can invoke later by appending parentheses to it, i.e. addTwo().
The parameter you pass to addTwo, i.e. 1on invokation addTwo(1) is passed to the add function, because addTwo is nothing more than an add function where the amount var has a fix value of 2.
var addTwo = makeAddFunction(2);
When you call makeAddFunction(2) initially, the amount var is within its function scope where add can see it. addTwo now is set to the add function that makeAddFunction(2) returned.
addTwo(1)
Remember addTwo is now set to what makeAddFunction(2) returned, which is the function add, and amount is set to 2 within makeAddFunction(2)'s scope. add just returns its argument (1), plus the amount (2) in makeAddFunction(2)'s scope.
The same goes for addFive(5).
Javascript Ninja or The Good Parts are good reads that explain closures in detail. I'd highly suggest picking up those.
Follow the SO Linked/Related Questions on the right. Anyway ..
This is explained the article, albeit with a lot of fluff. Anyway, with a bit of fluff-cutting here is a "annotated" version:
.. functions [do] not just package up [some code to run], but also an environment. [..] a function defined inside another function retains access [to lexical variables (like "amount")] that existed in [the outer function] at the point when [the inner function] was defined.
Thus, the [inner] add function in the above example, which is created when makeAddFunction is called, captures an environment [including the "amount" variable of the outer function]. It packages this environment, together with [the code to run], into a value [(which is a fancy way to say functions are just objects)], which is then returned from the outer function.
When this returned function ([which has been assigned to] addTwo and addFive) is called, [the called function has access to] the captured environment ([and the "amount" variable which still contains the value initially passed to makeAddFunction]). These two values ([which are currently named by] "amount" and "number") are then added, and the result is returned.
I am not found of the original usage of "value" and have edit those parts a good bit - in JavaScript, variables (not values) are bound in closures.
Javascript relies pretty heavily on higher-order functions. Functions can be returned, assigned to variables, and passed around as values. This comes in handy in a lot of situations, especially when dealing with evented programming (JS's direct lineage from the its most prolific implementation in the browser.)
http://en.wikipedia.org/wiki/Higher-order_function
What you are seeing is a function that creates a function. It could be considered a "factory" for a function with one preset argument.