Function Values and How Are They Executed (How They Work)? - javascript

I'm going through Eloquent JavaScript book and am on chapter 5 (Higher-Order Functions) currently. I'm doing good so far and have understood material clearly, but I've come to realize that I don't understand what function values are exactly and how they work. I do understand what functions are and am quite comfortable with the syntax of creating them using the function keyword as you would do in C for example.
Assume the following code from the book:
function forEach(array, action) {
for (var i = 0; i < array.length; i++)
action(array[i]);
}
var numbers = [1, 2, 3, 4, 5],
sum = 0;
forEach(numbers, function(number) {
sum += number;
});
console.log(sum);
How does the forEach function, when called, determine what is the number? How does it extract number from the numbers array. I do understand that action argument in the definition of forEach function "hooks" the action to the element which is currently pointed by the for loop, but I interpret the code as follows:
function(number) {sum += number;}action(array[i])
which doesn't make much sense.
If you could shed light on this issue I'd be more than thankful and also explain what the function value is exactly? How does it differ from function and/or function return value?
Thank you.

From what I've understood, I think that you are being confused by the JavaScript callback function.
In javascript, a function like this:
Look at your code:
function forEach(array, action) {
for (var i = 0; i < array.length; i++)
action(array[i]);
}
forEach(numbers, function(number) {
...
For each item of the array (first argument, accessed via array[i]) you are calling action with that value, action(array[i]).
In forEach(numbers, function(number) {, you have passed action (the second argument) as a function with one input. This is the function being called by forEach with each array element. With each pass of the for loop within forEach, this function is called with the new value.
I think trying this with other examples (just start your js console now and begin messing around) will help you to learn this concept.
If I made a function
function run(callback){
callback();
}
and called it like so:
run(function(){
console.log('foo bar baz');
});
I'd expect to see "foo bar baz" printed to the console.
If I now make a new function, and call it,
function withTheAnswer(callback){
callback(42);
}
withTheAnswer(function(theAnswer){
alert('The answer is ' + theAnswer);
});
I'd expect 42 to be alerted.
Honestly, as you start to learn more about JS, you'll see this used a lot, and therefore fully understand it.

I don't understand what function values are exactly and how they work
A function (in JavaScript) is an object that can be called. A function call is nothing special, it is just any expression (like a variable evaluation) followed by a pair of parenthesis with arguments in between.
You could write
var addToSum = function(number) {
sum += number;
};
forEach(numbers, addToSum);
or
function addToSum(number) {
sum += number;
}
forEach(numbers, addToSum);
and it means basically the same: You have a function object, a variable addToSum that refers to it, and it is passed to the forEach call.
How does the forEach function, when called, determine what is the number?
It doesn't know anything about the numbers. All the forEach function sees are an array value (referred to by the parameter name array) and a function value (referred to by the parameter name action). Then it loops over that array, and calls the action function with each of the elements. Only inside the called function this array element is know as number.
I interpret the code as follows: function(number) {sum += number;}action(array[i]) which doesn't make much sense.
If you expand the variable to its value, the variable name disappears:
(function(number) {sum += number;})(array[i]);
which does actually make sense - as I've written above, a function call is just an expression followed by parenthesis. And that expression needs to evaluate to a callable object, which this function expression does.
You might also rewrite it as
function action(number) { sum += number; }
action(array[i]);
if that make more sense to you.

action attribute is a function. This function doesn`t called until you put: 'action([a number])'. Then inside the for loop for each element of array attribute is called the function action with corresponding number.
As #theonlygusti says this function are called callbacks.

Related

Passing an entire array from a function to another function JavaScript

I know there are lots of answers already about this query but my question is on the receiving function.
Say I have three functions:
function A(a){
var j = getList(a);
j != null? process.apply(null,j): null;
}
function getList(a){
// returns an array like array[][] with no definite size
}
// I know this function should accept multiple arguments but I want the whole array to be passed
function process(j){
// I want to loop the array here but it seems like
// the argument passed is value of array[0][0]
//
}
I know that in c, it should be:
function process(j[][]){
And python has no problem just passing j directly. Now, javascript makes me wonder how to implement this. Your help is very much appreciated.
Apply takes an array of arguments, but you are passing a single argument as an array.
There are a couple ways to solve this, one way is I just wrapped j with [j] in the apply, that way its actually passing the array as the first element in the array of arguments.
I'm sure there is a better way to explain that, but I couldn't think of it.
function A(a){
var j = getList(a);
j != null? process.apply(null,[j]): null;
}
function getList(a){
// returns an array like array[][] with no definite size
return a;
}
// I know this function should accept multiple arguments but I want the whole array to be passed
function process(j){
console.log(j);
// I want to loop the array here but it seems like
// the argument passed is value of array[0][0]
//
}
A(["1","2"]);

Struggling to Understand the Parameter Content when using .map on Function Expressions

So I'm looking at function expressions.
This is the code I'm playing with:
var modifiedNames = [ "Thomas Meeks",
"Gregg Pollack",
"Christine Wong",
"Dan McGaw" ];
modifiedNames.map(function(cheese) {
alert("Yo, " + cheese + "!");
});
It works fine but I'm having trouble understanding part of it. I grasp what .map is doing but the parameter is really throwing me. How is the parameter collecting the array's information? I called it cheese as that's just my go-to test word.
I have read a couple of explanations but I'm just not grasping it, hoping somebody here could simplify the explanation somewhat. Thank you.
You're passing the function to .map(), which then runs a loop, and invokes the function on every iteration, passing it the current item.
Think of it like this:
for (var i = 0; i < array.length; i++) {
callback(array[i]);
}
Here array is the Array on which you called .map(), and callback is the function you passed in.
This isn't so mysterious now. It's just calling your function in a loop.
Of course, .map() does more work than this and passes more args, but this shows how the parameter gets populated.
A somewhat more complete implementation of a map would look like this:
Array.prototype.myMap = function(callback, thisArg) {
var result = new Array(this.length);
for (var i = 0; i < this.length; i++) {
if (i in this) {
result[i] = callback.call(thisArg, this[i], i, this);
}
}
return result;
};
Are you asking how exactly this is working internally?
.map is using a for loop behind the scenes and passing each element within the array to the cheese pointer. So cheese will be "Thomas Meeks" and it will alert it and then continue on and on.
How is the parameter collecting the array's information? I called it
cheese as that's just my go-to test word.
cheese is the named function parameter, which defines the passed parameter identifier within the scope of the function. The same as
function fn(cheese) {
console.log(cheese)
}
fn("and crackers");
Or using .map()
["and crackers"].map(fn);
See also Why does .then() chained to Promise.resolve() allow const declaration to be reassigned?

Anonymous function as callback [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
I am seeking help understanding why the way I am using anonymous functions are erroring in some circumstances.
In the snippet below I popuplate 2 arrays with functions which are invoked at a later stage.
var arr1 = [];
var arr2 = [];
// callback function
var func = function(i){
return function(){$("body").append(i);}
};
var i = 1;
while(i <= 5)
{
arr1.push(function(){$("body").append(i);});
arr2.push(func(i));
i++;
}
// invoke functions
$("body").append("Output from arr1 == ");
for(var c = 0; c < arr1.length; c++){ arr1[c](); }
$("body").append("<br> Output from arr2 == ");
for(var c = 0; c < arr1.length; c++){ arr2[c](); }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Now, I think I understand why arr1 outputs 66666, because at the time of invocation, i == 6 and becuase it has not been stored as a param within that function at time of creation, i retains it's last known value?
What I really don't understand is why i recieve TypeError: arr2[c] is not a function When I change the callback function to:
var func = function(i){
$("body").append(i);
};
Why does this happen and is this the most appropriate / elegant way to achieve this functionality.
For the first part of the question, you are right, it will retain the latest known value. To avoid that, you need to use closure. For example:
(function(x) {
arr2.push(func(x));
})(i);
Closure can often be used as a "scope hack". In this case, it will only ensure that the injected value is the constant current value of i.
For the second part of the question, your confusion is probably caused by the fact that you insert the result of the function (i.e.: func(i)) instead of the function itself (func).
In the first scenario, you return an explicit function(){...} so your array will contain a function that you can call with operator "()".
In the second scenario, in which you return $(<...>).append(), it's not guaranteed anymore that your return value is a function. In that case, the result is "jQuery" (see: jQuery append) and not a function, hence the error is correct. You cannot use the value as a function.
One way out is:
arr2.push(func);
Then:
arr2[c](c);
Or probably this:
(function(x){
arr2[x](x);
})(c);
If needed, it can be helpful to always console.log what is populated inside your arrays before assuming it right. Since Javascript is not a typed language, you may go for a little while before suspecting anything wrong as it will seem work as intended.
Hope this helps!

Javascript: confuse about usage of function call method

I achieve a forEach function:
function forEach(arr, fn) {
for (var i = 0; i < arr.length; i++) {
fn.call({}, arr[i], i);
}
}
what I confused is about fn.call({}, arr[i], i);
the first parameter is pass empty just like above {} is better
or pass this in: fn.call(this, arr[i], i); is better?
Or it doesn't matter
It matters quite a bit. The first parameter to .call() is the value to be used for this inside the called function. Thus, it doesn't make sense to talk about what value is "better"; the right value to pass is the one you need in order for the called function to operate properly.
For example, if you want to call a function on the Array prototype, then the value of this inside that function has to be something that "feels like" an array (a "length" property and numerically-indexed properties). Thus:
var sneaky = {
"0": "hello",
"1": "world",
"length": 2
};
alert( Array.prototype.join.call(sneaky, " - ") ); // "hello - world"
That works because that function expects this to refer to the array to be joined.
There are as many other examples as there are functions that have expectations about this. In your sample code, passing {} gives the called function a this reference to that newly-created empty object. Will that work? I don't know, because that function could expect anything. There's no way to find out, either, except by looking at the code (or trusting documentation). If all you know is that it's some random arbitrary function, then {} is a reasonable guess, though undefined might be better, to force early failure.
Personally I would go with passing this. By passing {} you are limiting the flexibility of your function. You will never be able to bind another object to this function the way it is currently written. This won't work:
forEach.call(newContext, array, fn)
Neither will this:
forEach(array, fn.bind(newContext));
By binding {} inside your forEach you are adding unexpected behavior.

Converting a loop into a recursive function

I wrote a function yesterday to count the number of "a" characters in a string. My teacher told me to refactor the code into a recursive function and I don't really know how to do so.
I would like some feedback on the subject, and by the way I'm an absolute beginner in JavaScript.
function numberOfA(n){
var numberA =0;
for (i=0; i<=n.length; i++){
if(n.charAt(i)== "a" ){
numberA++;}
}
return numberA;
}
to call the function following piece of code :
var n = prompt("type a word");
var output = numberOfA(n);
alert (output);
Thanks in advance !
The goal of recursion is to make a function which calls itself.
You might have mutual-recursion -- function A calls function B, calls function A... but that's certainly not needed here, and is better suited for when you know that you need to do two distinct things (one per function) and know that you need to do them in a leapfrog pattern.
Where recursion comes into play is when you're thinking about loops.
Normally, when you're doing things with loops, you might end up having two or three loops inside of one another.
Instead of worrying about managing loops, recursion is a way of thinking about what happens in a single-iteration of a loop, and writing ONLY the code needed to do that.
A really simple example of singular recursion might be to log all elements of an array to the console.
This is not a practical example -- it's a trivial example which has most of the pieces you need to make practical examples.
var array = [ "one", "two", "three", "four" ];
function listNextItem (array, index) {
var item = array[index];
if (!item) { return; }
console.log(item);
listNextItem(array, index + 1);
}
listNextItem(array, 0);
I've created a very simple function which looks like the inside of your innermost loop.
It sets an item variable, based on array[index].
If it doesn't exist, we're done, and we can return out of the function, so we don't try to go on forever (this is very important in recursion).
If it does exist, we log the item's value.
Then we call the exact same function, and pass it the exact-same array, but we pass it the value of index + 1.
Did this change anybody's life, or make loops obsolete?
Not really.
But it's the first step to getting recursion.
The next step is getting a return from recursion.
function recursiveAddOne (current, max) {
if (current === max) { return current; }
return 1 + recursiveAddOne(current + 1, max);
}
var total = recursiveAddOne(0, 3); // === 3 + 1 + 1 + 1
total; // 6
Normally in my return statement, I'd be sending the answer back to the variable in the outside world.
I'm still doing that, but here I'm adding a call to the same function, as part of my return.
What does that do?
Well, the outside function can't return a value until the inside function returns.
The inside function can't return a value until ITS inside function returns...
...and it goes all the way down until my termination-condition is met.
That condition returns a value to its outer function. That outer function returns that added value to ITS outer function... ...all the way up to where the outermost function gets handed the value of all of the other functions put together, and then returns THAT to the outside world.
It's like giving each Russian Matryoshka ("babushka") doll a piece of work.
You start with the biggest one, and go all the way inside to the tiniest one.
The tiniest one does its work first, and hands it back to the next one, which does its work and hands that back... ...all the way back until you're outside again.
Well, the basic concept of recursion is solving a problem with a smaller version of itself.
You have a function, numberOfA which gives you the length of a string(or maybe substring).
So let's say you have the string "javascript' the first string is at index 2.
It's logical to say that the number of as in your string is equal to 1 plus the number of as in the entire substring after the first a.
So what you do, is you add 1 to the number of as in the substring vascript
So here's some psudocode
function numA(str)
{
var substring = substr(index_of_first_a, str.length - index_of_first_a
return 1 + numA(substring);
}
function numberOfA(n, count){
if(!n.length) {
return count;
}
if(n.charAt(i)== "a") {
++count;
}
return numberOfA(n.substr(1), count);
}
var numberA = numberOfA('asdfafeaa', 0);
Try this:
function numberOfA(n) {
return n == "" ? 0 : (n.charAt(0) == "a" ? 1 : 0) + numberOfA(n.substring(1))
}
Here's how it works:
If n is the empty string, return 0 and finish the recursion. This is the base case of the recursion.
Else if the character at the first position in the string is an "a" add one, if not add zero and either way advance the recursion by removing the first character from the string. This is the recursive step of the recursion.
As you can see, every recursive solution must have at least a base case and a recursive step.
<!DOCTYPE html><html lang="en"><body><script>
var foo = function foo() {
console.log(arguments.callee); // logs foo()
// callee could be used to invoke recursively the foo function (e.g. arguments.callee())
}();
</script></body></html>
arguments.callee function will call the currently being executed method.

Categories