DEV Community

Cover image for TypeError: Cannot read properties of undefined (reading 'forEach')
Ifeanyi Chima
Ifeanyi Chima

Posted on • Edited on

TypeError: Cannot read properties of undefined (reading 'forEach')

Have you ever encountered this error in javascript before TypeError: Cannot read properties of undefined (reading 'forEach') there are many a causes for this error, but today, we would look at one. Take a look at the code below.



// index.js
const printNumbers = {
    phrase: "The current value is",
    numbers: [1, 2, 3, 4],
    loop: () => {
        this.numbers.forEach((number) => {
            console.log(this.phrase, number)
        })
    }
}

printNumbers.loop();


Enter fullscreen mode Exit fullscreen mode

to run this code open terminal and run node index.js. It will throw an error



TypeError: Cannot read properties of undefined (reading 'forEach')


Enter fullscreen mode Exit fullscreen mode

BMC

Cause

To understand what caused the error, we need to understand scope and arrow functions in javascript.

In javascript, Scope refers to the current context of code, which determines the accessibility of variables to javascript. There are two types of scope, Global and Local scope.

please refer to my other tutorial to understand more about scope.

An Arrow function doesn't have its own this value. It uses the this value of the enclosing lexical scope. In the code above, the this keyword in arrow function should refer to properties and methods (function) of the printNumbers object. However, objects in javascript do not have a lexical scope, therefore an arrow function will look outside (beyond) the object for the value of this, what is outside ? the global scope (window object) which does not have the numbers property. Therefore, the Javascript engine adds the numbers property to the window object and sets its value to undefined.

To fix the issue, you should use traditional functions as the method (function) of the object.

here is the same code, modified



// index.js
const printNumbers = {
phrase: "The current value is",
numbers: [1, 2, 3, 4],
loop(){ // ==> changes made
this.numbers.forEach((number) => {
console.log(this.phrase, number)
})
}
}

printNumbers.loop();

Enter fullscreen mode Exit fullscreen mode




answer

The traditional function re-binds this keyword.

Thank You, Please follow me

linkedin.com/in/ifeanyi-thankgod-chima/
https://twitter.com/ifeanyiTchima

Buy Me A Coffee

Top comments (1)

Collapse
 
punund profile image
punund

Cause of many troubles is poor design solutions. There is nothing that mandates the loop() to be a method of printNumbers object.

Take it out, making it a pure function:

const loop = n => {
   n.numbers.forEach(number => {
      console.log(n.phrase, number)
   })
}

loop(printNumbers)
Enter fullscreen mode Exit fullscreen mode

and don't ever think of this again.