1

Why is it throwing error in case 1 but not in case 2?

case 1:

export class AppComponent implements OnInit{
    obj={
       name:"XYZ",
       age:"22",
       height:"5"
    }
    ngOnInit() {
       this.calling();
    }
          
    calling(){
        if(true){
            Object.keys(this.obj).forEach(function(key) 
                  {
                       console.log(key,this.obj[key])
                  }
              )
         }
     }
 }

error: Cannot read property 'obj' of undefined

case 2:

export class AppComponent implements OnInit{
    ngOnInit() {
        this.calling();
    }
    
    calling() {
        if(true){
            let obj={
                name:"XYZ",
                age:"22",
                height:"5"
            }
            Object.keys(obj).forEach(function(key) 
                {
                    console.log(key,obj[key])
                }
            )
        }
    }
}

No error is shown in console in this case.

3
  • 1
    Use arrow operator , you will not face any issues here then Commented Jul 15, 2020 at 18:42
  • 1
    This is happening because in forEach callback the value of this is undefined , it is not longer the class variable. Commented Jul 15, 2020 at 18:42
  • In your first method context is changed inside the forEach. You can get it done by using below code. var self = this; console.log(key,self.obj[key]) Commented Jul 16, 2020 at 4:29

2 Answers 2

2

When you use function() to define a function, the value that this refers to changes. If you want this to continue to refer to the class, then use an arrow function.

export class AppComponent implements OnInit {
  obj = {
    name:"XYZ",
    age:"22",
    height:"5"
  }

  ngOnInit() {
    this.calling();
  }
        
  calling(){
    if(true){
      Object.keys(this.obj).forEach((key) =>
        {
          console.log(key, this.obj[key])
        }
      )
    }
  }
 }

You can also fix this by calling bind() on the function in order to set this within the function.

export class AppComponent implements OnInit {
  obj = {
    name:"XYZ",
    age:"22",
    height:"5"
  }

  ngOnInit() {
    this.calling();
  }
        
  calling(){
    if(true){
      const func = function(key) {
        console.log(key, this.obj[key])
      };

      Object.keys(this.obj).forEach(func.bind(this));
    }
  }
 }
Sign up to request clarification or add additional context in comments.

Comments

0

You don't have a grasp of scope in Javascript.

In your first example, your callback function has its own this defined, so the outer functions this is not accessible.

To fix that you can use an arrow function (or you can use .bind(this) but I don't really ever use that).

//arrow functinon
Object.keys(this.obj).forEach((key) => {
    console.log(key,this.obj[key])
)}

Here's some more reading on arrow functions vs bind: https://www.freecodecamp.org/news/when-and-why-you-should-use-es6-arrow-functions-and-when-you-shouldnt-3d851d7f0b26/

Your second example works because you defined obj with let so its accessible inside your function.

Here's a good article on var/let/const https://www.deadcoderising.com/2017-04-11-es6-var-let-and-const-the-battle-between-function-scope-and-block-scope/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.