Hi I just took a 2-3 week break from coding and now returning to this. I think my problem as it was before is that I have trouble using a function within a function or callback functions within a function.
I’ve sadly been struggling with this for some time and I’ve been finding myself struggling to a point where I’m losing interest. I’ve gone back to redo sections like this a few times now. Each time I do this I feel more ambition dripping away.
I’m here now at this problem again and I feel my main issue is effecting me again and I don’t know where exactly the disconnect happens. Hope someone can help, thanks
**Your code so far**
// The global variable
var s = [23, 65, 98, 5];
Array.prototype.myMap = function(callback) {
var newArray = [];
// Only change code below this line
for(let i = 0; i < s.length; i++) {
newArray.push(s[i]);
}
// Only change code above this line
return newArray;
};
var new_s = s.myMap(function(item) {
return item * 2;
});
console.log(new_s);
**Your browser information:**
User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36.
Do you have a question? Is there something specific?
Looking at what you have, you have the basic components there, you just need to apply the callback function. In JS, functions are just variable, like any other (technically a kind of object).
You are invoking it here:
var new_s = s.myMap(function(item) {
return item * 2;
});
so you are passing in:
function(item) {
return item * 2;
}
That is what you are passing in and it is what is getting stored in the parameter callback. Inside your myMap method definition, you can just call that like callback().
To get this to work, I added that to your code, calling callback with the right parameter. I had to add that to one line and got your code to pass.
I just don’t know how to write code taking these callbacks in. I don’t see how they combine. Does that make sense?
Basically I have
Array.prototype.myMap = function(callback) {
var newArray = [];
// Only change code below this line
for(let i = 0; i < s.length; i++) {
newArray.push(s[i]);
}
// Only change code above this line
return newArray;
};
and
var new_s = s.myMap(function(item) {
return item * 2;
});
How does
function(item) {
return item * 2;
});
Get placed into
function(callback) {
var newArray = [];
// Only change code below this line
for(let i = 0; i < s.length; i++) {
newArray.push(s[i]);
}
// Only change code above this line
return newArray;
};
I’m happy to spend 20 hours a week coding and want to do that, but I can’t seem to learn what I need. I even messaged someone on Twitter and they told me to read this Variable scope, closure but I don’t understand these types of long documents. I’m being honest about my shortcomings hoping I can find a solution. I’d be willing to spend 10 hours just on this concept alone if need be
This challenge is a bit tricky because you need to use this because you are writing a function that works for all arrays.
Also, I don’t see where you are using the callback.
Pulling back to a ‘big picture’, this challenge is asking you to make a new method that will work on all arrays.
All arrays have certain built in properties and methods, like length, map(), every(), etc. You need to make a new method that works for every single array. We do this by adding a new method to the prototype for every array.
Since you are trying to make a new method that operates on the elements of an array, you need a way to access the array and its elements. This is what this does for you.
let s = [23, 65, 98, 5];
// I can't write the function to refer to s
// because then it would only work for
// *one* array, not *all* arrays
s.myNewMethodForAllArrays(....)
Now, another big picture idea is that functions can be passed around just like arrays or objects. You can give a function as an argument to another function. Look at this
// Print the numbers 1-5 with custom formatting
function printOneToFive(callback) {
for (let i = 1; i <= 5; i++) {
console.log(callback(i));
}
}
// A nice formatting function
function makePretty(num) {
return "--*****--" + num + "--*****--";
}
// A bad formatting function
function makeMessy(num) {
return "890721498721948" + num + "98127498";
}
// Test
printOneToFive(makePretty);
printOneToFive(makeMessy);
Yeah, it took me a bit to wrap my head around callbacks. Really, the idea is very simple - pass in a function to be used at some point. In this case, myMap doesn’t really care what callback does, just that it needs to use that function. But it did take a bit for me to wrap my head around it. Writing things like this were a big part of what made it click. But don’t get frustrated.
@JeremyLT thanks for giving me a example like this to dig into the function as argument to function stuff. Good news is I do understand your other points about how Array.prototype is used to create a method that can be used in other places, so we should use this.
Can you explain how this works exactly? I was going to attempt to ask a specific question about it but I think it’s better not to since it’s still strange to me.
@kevinSmith thank you. Unfortunately I haven’t been able to connect the dots on this but I’m staying at it
Does that makes sense? We are passing in a reference for a function.
In our printOneToFive function, we accept a parameter:
function printOneToFive(callback) {
for (let i = 1; i <= 5; i++) {
console.log(callback(i));
}
}
That parameter is called “callback”. When we called it the first time with this:
printOneToFive(makePretty);
We passed in a reference to the function makePretty. That gets accepted in the printOneToFive function as the parameter callback. So, at this point, callback is a reference to the function makePretty. The function printOneToFive doesn’t know and doesn’t care that it is called makePretty in the outer scope. All it knows is “I got passed a function and I stored it in ‘callback’”. It then applies that function.
Technically we could have used the makePretty from the global scope instead of passing it in. But that would make printOneToFive less flexible because then we’d have to have separate versions for pretty and messy. That is the strength of callbacks.
Gotcha so callback is replaced by makePretty and so when I see that I envision a function that combines the two as follows (this may be what I’m having trouble with):
function printOneToFive(num) {
for (let i = 1; i <= 5; i++) {
console.log(num(i));
return "--*****--" + num + "--*****--"
}
}
This is the way I try to think about it but it seems to get confusing for me when I’m looking at the other exercises. What would be a better way to think about it
Put another way, does it make sense that these all do the same thing:
function printOneToFive1() {
for (let i = 1; i <= 5; i++) {
console.log("--*****--" + i + "--*****--");
}
}
printOneToFive1();
// *****
function printOneToFive2() {
function makePretty2(num) {
return "--*****--" + num + "--*****--";
}
for (let i = 1; i <= 5; i++) {
console.log(makePretty2(i));
}
}
printOneToFive2();
// *****
function makePretty3(num) {
return "--*****--" + num + "--*****--";
}
function printOneToFive3(callback) {
for (let i = 1; i <= 5; i++) {
console.log(callback(i));
}
}
printOneToFive3(makePretty3);
The first one hard codes the stuff into the console.log. In the second one, we abstract it into a function. In the third one, it’s also abstracted into a function but instead of being defined in out printOneToFive3 function, it’s defined outside that and passed in as a parameter, aka a callback.
@JeremyLT Ok got it. So any place that has callback in it receives the part of the callback function? @kevinSmith yeah I think so.
Am I correct in thinking about functions in functions like this? It seems it can get really confusing when doing more complex functions.
I ended up solving this with the following
// The global variable
var s = [23, 65, 98, 5];
Array.prototype.myMap = function(callback) {
var newArray = [];
// Only change code below this line
for(let i = 0; i < this.length; i++) {
newArray.push(this[i] * 2);
}
// Only change code above this line
return newArray;
};
var new_s = s.myMap(function(item) {
return item * 2;
});
console.log(new_s);
but it felt weird just redoing this part manually. I felt I wouldn’t have needed to type it out
var new_s = s.myMap(function(item) {
return item * 2;
});
Unfortunately, I don’t think I really understand that well