0

I'm attempting to run this code:

public isDataValid(obj: any){
    let isCriteriaValid = function (){
      for(let element in obj){
        if(!this.isStringOrObjectValid(element)){
          return false
        }
      }
      return true
    }
    return (obj != undefined) ? isCriteriaValid() : false
}

A quick explanation:

Running this function checks to see if an object is valid by checking all of the elements in it.

I have an issue with the "this" context being sort of "erased".

tblev
  • 134
  • 1
  • 8

2 Answers2

1

The issue was a little thing called scope. The scope isn't "erased", the "this" keyword is referring to a new scope.

The scope of the isStringOrObjectValid function is now the function it was declared in which is the local variable. I fixed it by passing in the object that I wanted to run the function off of to the ternary statement. Like this:

let isCriteriaValid = function (service){
  for(let element in obj){
    if(!service.isStringOrObjectValid(element)){
      return false
    }
  }
  return true
}
return (obj != undefined) ? isCriteriaValid(this) : false

If anyone has a better way, I'd be open to learning about this type of scope issue.

tblev
  • 134
  • 1
  • 8
1

you should be able to pass the scope to a variable and then use that

public isDataValid(obj: any){
  **let that = this;**   
    let isCriteriaValid = function () {
        for (let element in obj) {
          if (!**that**.isStringOrObjectValid(element)) {
            return false
          }
        }
        return true
      }
      return (obj != undefined) ? isCriteriaValid() : false
    }

but really in this day and age you should be using an ES6 arrow function and the scope will be maintained ... something like this

public isDataValid2(obj: any) {
    let isCriteriaValid = () => {
      for (let element in obj) {        
        if (!this.isStringOrObjectValid(element)) {
          return false;
        }
      }
      return true;
    };

    return obj !== undefined ? isCriteriaValid() : false;
  }
72GM
  • 2,322
  • 3
  • 17
  • 26
  • Yes, you can do this. Though why not pass it in as a parameter? – tblev Sep 18 '20 at 19:44
  • 1
    you're splitting hairs tbh and life is too short to worry about tiny differences in those 2 ways .... you should really be doing it in ES6 so I've updated my answer for this – 72GM Sep 21 '20 at 14:43
  • Very cool, I've used this with subscribes like `() => {}` for complete but I didn't think of it this way. – tblev Sep 21 '20 at 15:29