Search code examples
javascriptpromise

Why is this function inside the constructor referencing an object instance even though it's not a property?


function Promise (callback){

    //this = {}
    //because of "new" keyword, an empty object is automatically created, and the "this" is referencing to that object.
    
   this.status = "pending";

   const resolve = () => {
            this.status = "fulfilled";
            console.log("status is: " + this.status)    
    };
  
    callback(resolve);
    
    //return this 
    // at the end, javascript automatically returns the "this" object.
}

console.log("start")

const p1 = new Promise((resolve) => {
    setTimeout(() => resolve(), 3000);
});

setTimeout(() => console.log(p1.status), 4000)

//output:
 //start
 //status is: fulfilled
 //fulfilled

So now, p1 is an object instance of Promise.

After the "this" object is returned to the p1 variable, the resolve function is yet to be executed, and after 3 seconds, it then executes.

The resolve function is not a property or method of an object because it's not written as this.resolve(){...} or Promise.prototype.resolve()....

My question is: When the resolve function is passed in the callback: callback(resolve), the "this" inside the resolved function is referencing the newly created object : this = {} and not the p1 object?

but when the resolve function is invoked, it changes the status of p1. So it's this is actually referencing to the p1 object. Why is that? I'm confused.

...and even if I make it like this:

this.resolve = () => {
            this.status = "fulfilled";
            console.log("status is: " + this.status)      
    };
  
callback(this.resolve);

the this in the this.resolve will still be referencing the newly created object: this = {} from what I understand.

The code above is from: https://medium.com/swlh/implement-a-simple-promise-in-javascript

I just modified it.


Solution

  • The arrow function declaration of resolve() captures the lexical value of this at the point of the function declaration. Because that lexical value of this is the this inside the constructor, it will naturally point to the newly created object that was created by that constructor.

    That lexical value of this is hardwired into that specific declaration of resolve (that's how arrow functions work).

    Note, that each running of the Promise constructor creates a NEW copy of the resolve function with a different lexical this bound to it.

    This "binding of the lexical this" is a very important feature of arrow functions and would not be the case if you did function resolve() {} instead.

    My question is: When the resolve function is passed in the callback: callback(resolve), the "this" inside the resolved function is referencing the newly created object : this = {} and not the p1 object?

    But, p1 and this inside the resolve() function are the same object. They are the same object. You can attach a unique property to one and you will see it on the other. Or you can compare them directly. They are the same object.