Logic behind forEach and callback functions

thank you for your response sir

so here the compiler knows my foo function will accept only two arguments a function and an array with the same order ?

1 Like

so the key is here a.map(f) a will be an array and f will be a function from this line ,right ?

1 Like

The parameters don’t dictate order, as we know, the arguments do. Our parameters are essentially hoping they describe the expected argument. We the designer knows what objects we wish to operate upon and in what way.

The compiler only sees the references, not the actual objects. Compliance within our code architecture is what makes everything work, in the end. OUR code complies with the dictates we, or built in methods/functions have set out.

a.map(f)

We complied at first by passing a function reference that exists, and an Array object, which has a map method in its prototype. That method takes a callback which is the function we wish to repeat through iteration of the array.

2 Likes

i think i got it now !! really thanks
the problem was that i’m coming from another language “c++” which need to declare the parameter’s with a data type before write your function’s body
like here: int fun_name(int x, int arr[10]) {function body} ;
so it was easy to imagine what will be the argument’s datatype but here in JS it’s different so i got confused but you made it clear now !! thanks again ! :smiling_face_with_three_hearts:

1 Like

You’re welcome!

Hopefully you don’t take any bad habits (or ideas) back into your C++ environment; (grin).

JavaScript is loosely typed when it is not run in strict mode. By design we can build in strong data typing, but out of the box JS lets us do pretty much anything we want. If we do not want the type of a variable to ever change, we do have const, but then we can only change values if that variable is a reference to an object, not a singular value. Having protected arrays, objects (and functions) is a nice touch.

Bottom line, think in terms of references and this whole concept becomes practical and easy to implement.

1 Like

oh… i needed this line since my first step in JS journey … thinking of the JS names like pointers is really make many things so clear!!

const x = [1, 2, 3] 
const y = x  
y[0] = 9 
console.log(x) 
console.log(y) 
>> [9, 2, 3]
>> [9, 2, 3]

i I was really confused and wondering how is changing the y affects the x !! how this magic happened ! :joy:
but after your response i understood it that is because x and y is referring to the same value and this value is an array which is mutable so i can change it’s value which is visible through all of its names(pointers) !! but if i tried the same thing with numbers like

let x = 3 
let y = x
y = 6

x will still 3 and y will be 6 that is because numbers are immutable so you can’t change the same value but now y is referring to another value ‘6’ .
i’m really happy!!! thanks!!! :heart_eyes:

5 Likes

I just did it like this:

const fruits = ['mango', 'papaya', 'pineapple', 'apple'];

// Iterate over fruits below
fruits.forEach(fruit => {
  if (fruit[0] !== 'a') {
    console.log(`I want to eat a ${fruit}`)
  } else {
    console.log(`I want to eat an ${fruit}`)
  }
});
2 Likes

As this is a very simple check, you don’t want to write too much code for it. So, you could actually write it like this instead (though it’s up to you, it’s just a matter of preference):

const fruits = ['mango', 'papaya', 'pineapple', 'apple'];

// Iterate over fruits below
fruits.forEach(fruit => {
    console.log(fruit[0] !== 'a' ? `I want to eat a ${fruit}` : `I want to eat an ${fruit}`)
});

Do note that not because something can be written in a shorter way means it’s going to be readable

still repetitiveness, which we could eliminate:

const fruits = ['mango', 'papaya', 'pineapple', 'apple'];

// Iterate over fruits below
fruits.forEach(fruit => {
    console.log(`I want to eat ${fruit[0] === 'a' ? 'a' : 'an'} ${fruit}`)
});
1 Like

Yeah, of course. Though as I said, we must keep our code readable.

Do note that not because something can be written in a shorter way means it’s going to be readable

There are fruits that begin with every vowel in the alphabet.

const fruits = [`Acai`, `Acerola`, `Amanatsu`, `Apple`, `Apricot`,
 `Avocado`, `Eddo`, `Elephant Apple`, `Engkala`, `Escobillo`,
 `Elderberry`, `Eggfruit`, `Evergreen Huckleberry`, `Entawak`,
 `Illama`, `Imbu`, `Indian date`, `Indian Wampi`, `Inga Acu`,
 `Indian Prune (Plum)`, `Indonesian Lime`, `Imbe`, `Indian Fig`,
 `Olive`, `Orange`, `Olosapo`, `Otaheite Apple`, `Ogeechee Lime`,
 `Oval Kumquat`, `Ugli Fruit`, `Uniq Fruit`, `Ugni`, `Umari`,
 `Umbu`, `Ume`, `Umkolo`, `Uvalha`]

const articleChooser = x => {
  console.log(`I want to eat ${`AEIOU`.includes(x[0]) ? `an` : `a`} ${x}`)
}

fruits.forEach(articleChooser)
1 Like

Hi I’m new and very raw but the code above should be ‘a’ ? ‘an’ : ‘an’}
No?
Hard for me to follow what you all are saying but I’m getting some of it.

I meant ‘a’ ? ‘an’ : ‘a’}

sorry

when this condition:

fruit[0] === 'a' 

evaluates to true, use 'a', else (:) use 'an'

could be that I flipped it.

Trying to learn this stuff and it’s very helpful to read the issues and the answers.
Thx.

Thanks for this. I tried adding more parameters to the callback function:

const fruits = [‘mango’, ‘papaya’, ‘pineapple’, ‘apple’];

fruits.forEach((item, item1, item2, item3) => {
console.log('I want to eat a ’ + item)
})
when logging item, it logs the fruits. When logging item1, it logs numbers (i.e. 0,1,2,3) and when logging item2, it logs the entire array (mango,papaya,pineapple,apple). What is going on here!

why would you do this?

if we look at the documentation of forEach:

Array.prototype.forEach() - JavaScript | MDN

we can see that the callback takes minimal 1 parameter and max 3.

the first parameter is the current value
the second parameter will hold the index
the third parameter will hold the list

Could you explain to me, how you think .forEach work? I am trying to pinpoint what you are struggling with

Thanks for the response. I actually didn’t check the doc before messaging you but I asked about adding more than 1 parameter because I looked at the naive implementation and saw that the theCallBackFunction() had one parameter: theArray[i]. I was wondering what would happen if theCallbackFunction() was inserted with more than one argument. So it seems like the implementation should be:

theCallBackFunction(theArray[i], i, theArray);

I think it could be useful to be able to access both the element and its index. Maybe save some processing effort/time instead of calling the indexOf() method?

The indexOf() method returns the first index at which a given element can be found in the array, or -1 if it is not present.

While the forEach method is intended to eliminate some of the repetitiveness of a for loop

const fruits = [‘mango’, ‘papaya’, ‘pineapple’, ‘apple’];

// Iterate over fruits below

fruits.forEach(function(fruit){

if(fruit[0]=== ‘a’){

console.log('I want to eat an ’ + fruit);

}

else if(fruit[0]=== ‘e’){

console.log('I want to eat an ’ + fruit);}

else if(fruit[0]=== ‘i’){

console.log('I want to eat an ’ + fruit);

}

else if(fruit[0]=== ‘o’){

console.log('I want to eat an ’ + fruit);}

else if(fruit[0]=== ‘u’){

console.log('I want to eat an ’ + fruit);}

else{

console.log('I want to eat a ' + fruit);

}

})

Why do i fix everything i touch? XD. In reality this strategy wouldn’t work. For example in words like “a university”, “a URL” etx.