Making my own ForEach() javascript - element is not defined
Asked Answered
M

9

6

I am making my own implementation of forEach in javascript, with the sole purpose of understanding the language better. To be more specific the temporary goal is to understand callbacks better.

This is how far I got until I got stuck.

function myForEach(array, callback) {
  for (let i = 0; i < this.length; i++) {
    callback(array[i]);
  }
}

function callback(element) {
  console.log(element); //insert logic
}

const array = [2, 4, 6, 8, 10];
arr.myForEach(array, callback(element));

I get the following error when running in node:

ReferenceError: element is not defined
    at Object.<anonymous> (C:\Users\Jonas\Desktop\FLEXBOX\test.js:54:31)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Function.Module.runMain (module.js:694:10)
    at startup (bootstrap_node.js:204:16)
    at bootstrap_node.js:625:3

I suspect it is because when the function is called, the element given as parameter in the callback function is not created. Which makes sense, but the real forEach loop when called does not pass in a value created yet?

arr.forEach((element /*does not exist yet?*/) => {
    console.log(element);
});

I have tried invoking the method with a lambda as well, which does not get a correct result either. But a different error

arr.myForEach(array, (element) => {
    console.log(element);
});

then it gives the error:

TypeError: arr.myForEach is not a function
    at Object.<anonymous> (C:\Users\Jonas\Desktop\FLEXBOX\test.js:58:5)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Function.Module.runMain (module.js:694:10)
    at startup (bootstrap_node.js:204:16)
    at bootstrap_node.js:625:3
Mangosteen answered 25/9, 2018 at 15:26 Comment(3)
The error you quote is not the error that code throws. You should provide a real minimal reproducible exampleSaimon
"I have tried invoking the method with a lambda as well, which does not solve anything." this ain't correct, it solves one problem, but your code still contains a few mistakes/errors.Sped
There are other problems with your code (don't have time to type a full answer now), but the immediate problem is that element is only defined inside callback. You should instead just be passing callback as a function reference.Natika
M
4

You have several errors, check this:

function myForEach(array, callback) {
    for (let i = 0; i < array.length; i++) { 
        callback(array[i]);
    }
}

function callback(element) {
    console.log(element); //insert logic
}

const array = [2, 4, 6, 8, 10];
myForEach(array, callback); 

The errors are (see comments):

function myForEach(array, callback) {
  for (let i = 0; i < this.length; i++) { // what is this? You need array.length
    callback(array[i]);
  }
}

function callback(element) {
  console.log(element); //insert logic
}

const array = [2, 4, 6, 8, 10];
arr.myForEach(array, callback(element)); 
// arr.myForEach is not possible, because myForEach is not a method of JS arrays 
// callback(element) this invokes a function, you just need to pass it like callback (without parentheses)
Monmouth answered 25/9, 2018 at 15:33 Comment(0)
M
10

This is how you can achieve it

    Array.prototype.myForEach = function(callback) {
      for (let i = 0; i < this.length; i++) {
        callback(this[i]);
      }
    };
    
    function callback(element) {
      console.log(element); //insert logic
    }
    
    var array = [2, 4, 6, 8, 10];
    array.myForEach( callback);

error element not defined is because in last line you use 'callback(element)' , in that line element is not defined

and to be able to call method on arrays like array.myForEach you have to attach it to prototype

NOTE: It is not advised to change the inbuilt prototypes though. Thanks for comments guys

Multitudinous answered 25/9, 2018 at 15:31 Comment(4)
I had built the same code, but one thing to note -- as you've attached it directly to the Array prototype, you have the pseudo-variable this that you reference. This means you can (and should) remove the array as a param to itself in the last line, and remove it as a required param in the first line.Drinking
Since you are working with the Array.prototype you may want to remove the reference to array and use only thisNyala
This is the answer i like the best so far! I like using this. also, since it makes it more generic. I will mark as answer when I can :)Replace
@JonasGrønbek Please note that modifying the prototype of native JavaScript elements can be risky and is generally considered a practice to avoid in production code. (it's also the reason we can't have Array.flatten.... thanks mootools ...)Patten
K
4

element is not defined

You're getting this because element is not defined when it encounters this line:

arr.myForEach(array, callback(element));`

That code says to immediately call callback, passing in a variable named element (which doesn't exist), then take the result of callback and pass it into myForEach

arr.myForEach is not a function

You're getting this because you didn't modify Array.prototype to have a myForEach function, and so arr.myForEach is undefined. The way you've written myForEach you should invoke it like this:

myForEach(array, (element) => console.log(element))

or

myForEach(array, callback);
Kauffmann answered 25/9, 2018 at 15:30 Comment(1)
This shows what is wrong, but it does not point me towards solving my problem. Thanks for the answer, but i will not mark it as one since it is not :)Replace
M
4

You have several errors, check this:

function myForEach(array, callback) {
    for (let i = 0; i < array.length; i++) { 
        callback(array[i]);
    }
}

function callback(element) {
    console.log(element); //insert logic
}

const array = [2, 4, 6, 8, 10];
myForEach(array, callback); 

The errors are (see comments):

function myForEach(array, callback) {
  for (let i = 0; i < this.length; i++) { // what is this? You need array.length
    callback(array[i]);
  }
}

function callback(element) {
  console.log(element); //insert logic
}

const array = [2, 4, 6, 8, 10];
arr.myForEach(array, callback(element)); 
// arr.myForEach is not possible, because myForEach is not a method of JS arrays 
// callback(element) this invokes a function, you just need to pass it like callback (without parentheses)
Monmouth answered 25/9, 2018 at 15:33 Comment(0)
G
3
const arr = [2, 4, 6, 8, 10];
myForEach(arr, callback); 

Function you written is supposed to be invoked in above manner.

Guesstimate answered 25/9, 2018 at 15:30 Comment(0)
P
2

there are several ways to go about it. What I think you were trying to go for was modifying the array itself to have your function, in which case the below code does that. Note that I am assigning the function to be a property of the instance of the array. You could also modify the Array.prototype ... but this is generally considered to be a dangerous and ill advised idea. (side note, in your code you aren't passing the callback into the function, you are calling callback(element) and passing the result (undefined) into the function.

function myForEach(callback) {
    for (let i = 0; i < this.length; i++) {
        callback(this[i]);
    }
}

function callback(element) {
    console.log(element); //insert logic
}

const arr = [2, 4, 6, 8, 10];
arr.myForEach = myForEach;
arr.myForEach(callback);

The other way you could do it would be to pass both the array and callback into a function, in which case you wouldn't want to use this.

function myForEach(array, callback) {
    for (let i = 0; i < array.length; i++) {
        callback(array[i]);
    }
}

function callback(element) {
    console.log(element); //insert logic
}

const array = [2, 4, 6, 8, 10];
//myForEach(array, callback(element));
myForEach(array, callback); 
Patten answered 25/9, 2018 at 15:40 Comment(2)
I have marked you as answer because you point out why the code does not work, and give a well explained solution. Thanks dgeare, a very pleasant answer!Replace
@JonasGrønbek glad I could help ^_^bPatten
E
1

The reason you are getting this error is that the 'element' is not referring to anything in this instance. You need to loop through the array, and then add the logic to each element, say that you would want to add two to teach element of your array, your callback function could look something like this:

function specificAFunction( arr ) {
let arrayResult = [];
arr.forEach( element => arrayResult.push(element + 2) );
return arrayResult;
};

and then you could call your first function with the function and your array of values:

const values = myFilter(myArray, specificAFunction);
Encipher answered 25/9, 2018 at 15:33 Comment(0)
K
0

Here you can create your own invoked print function accept a condition function

var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

Array.prototype.arrayPrint = function (calback)
{
    for (let index = 0; index < this.length; index++) {
        if (calback(this[index], index))
        {
            console.log(this[index]);                
        }
    }
}

function ifOdd(elem, index)
{
    return elem % 2 == 0;    
}

array.arrayPrint(ifOdd);
Kief answered 23/2, 2021 at 14:24 Comment(0)
C
0

If you are looking for your own forEach() like method in JavaScript, you can attach it to the Array.prototype using Object.defineProperty static method.

Code Snippet -

Object.defineProperty(Array.prototype, 'myForEach', {
  value: function(callback) {
    for(let i=0; i< this.length; i++) {
      callback(this[i]);
    }
  }
})

function callback(element) {
  console.log(element);
}

const array = [2, 4, 6, 8, 10];
array.myForEach(callback);
console.log(`***** ***** *****`)
array.forEach(callback);
Chalybite answered 30/10, 2022 at 18:24 Comment(0)
C
0

Here is code how to make your own myForEach that works identically as forEach except it doesnt have that array argument, having its own for loop and in callbackfn.call input "array" is referencing to object from which you called forEach function.

const array = [2, 4, 6, 8, 10];

function callback(element){
  console.log(element);
}


function myForEach(array, callbackfn, thisArg){
  for(let i = 0;  i < array.length; i++){
    callbackfn.call(thisArg, array[i], i, array);
  }
}


myForEach(array, callback);
Calamity answered 30/10, 2023 at 19:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.