Why this gets undefined in high order functions in Javascript?
          
            
          
        When a function has been used as a high order function (passed as an argument) they lose their awareness of this, even if they are in the same object. E.g:
    > function Person(name, gender) {
        this.name = name;
        this.sayHi = function (descriptor) {
            return `Hi ${descriptor()}`;
        }
        this.getName = function() {
            return this.name;
        }
     }
    > p = new Person("Jon");
    > p.sayHi(p.getName);
    'Hi undefined'
A quick way to solve this issue is by passing the function bound to the object. E.g.:
    > p.sayHi(p.getName.bind(p));
    'Hi Jon'
But wouldn’t be great to understand the source of this problem?
A matter of context
Why this happens? Well, in Javascript when you assign a function of an object to a variable/parameter, you are actually detaching that method from its object:
> const myFunc = instanz.myFunction;
// or 
> function myFunc2(f) {
    f();
 }
In such case, inside myFunction the value of this is not the same as intanz anymore, but it will get the value of this from the global context, which in strict-mode is undefined instead of the global window object.
Well, it doesn’t look very clear at the beginning, but with a short example it will be easier to understand.
An example to test the theory
- 
    Let’s create a test class that is aware of its context > function Soldier(numBullets) { this.numBullets = numBullets; this.checkStatus = function() { "use strict"; console.log(this === captain); console.log(`I am ${this}`); console.log(`I have ${this.numBullets} bullets`); } }
- 
    Create an instance captainto see whether it works as expected> captain = new Soldier(5); > captain.checkStatus(); true I am [object Object] I have 5 bullets
- 
    Let’s see what happens if we separate the function checkStatusfrom its objectcaptain:> captainStatus = captain.checkStatus; > captainStatus(); false I am undefined Uncaught TypeError: Cannot read property 'numBullets' of undefined
This confirms that checkStatus is detached from captain and that this is undefined.
Does this happen every time or only when it is in strict mode? If the directive strict mode is removed and you detach the function from its object again, then running this in your browser should get the global object window:
> function Soldier(numBullets) {
    this.numBullets = numBullets;
    this.checkStatus = function() {
        console.log(this === captain);
        console.log(`I am ${this}`);
        console.log(`I have ${this.numBullets} bullets`);
    }
  }
> captain = new Soldier(5);
> captainStatus = captain.checkStatus;
> captainStatus(); 
false
I am [object Window]
I have undefined bullets
This happened because in the browser window was the object that owned captainStatus at the moment of its execution. Try these same instructions again, but this time in a nodejs console to see what happens. Who is the owner of the method this time?
Conclusions
Each time we are going to execute functions in Javascript, it is important to remember that:
- A method can be detached from an object into a separated variable, e.g. const oprhan = obj.someMethod.
- How we invoke a function changes the context on which it is executed.
- During a function invokation, i.e. the invokation of a function that is not attached to an object, thisis going to be searched in the global context.
- The keyword thisisundefinedin a function invocation in strict mode.
It gets even more interesting when you learn that when using arrow functions in these scenarios you actually get a static context on different invokation types.
 
      
    
Leave a Comment