1

why this code compiles

var Person =  function() {
console.log("CALLED PERSON")};

Person.prototype.saySomething = function() {
console.log("saySomething PERSON")};

var ape = new Person();
ape.saySomething();

and this code throws error Cannot set property 'saySomething' of undefined

var Person =  async function() {
console.log("CALLED PERSON")};

Person.prototype.saySomething = function() {
console.log("saySomething PERSON")};

var ape = new Person();
ape.saySomething();
Ralph Sachi
  • 13
  • 1
  • 3

2 Answers2

4

When you use async function() {}, you are declaring an asynchronous function object. That's different than a regular function object. The asynchronous function object does not have a prototype.

So, when you try to do this:

var Person =  async function() {
  console.log("CALLED PERSON")
};

Person.prototype.saySomething = function() {
  console.log("saySomething PERSON")
};

Person.prototype is undefined because there is no prototype on an asynchronous function object. Thus attempting to assign something to Person.prototype.saySomething causes the error you see because Person.prototype is undefined.

There is some logic to this because an asynchronous function can't be used as a constructor because an asynchronous function always returns a promise so it can't ever return a new object as in let obj = new f(). So, there's no purpose in having a .prototype property because it can't be used that way.

If you really wanted to asynchronously create an object, you could always create an async factory function that returns a promise that resolves with an object.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • " an asynchronous function always returns a promise" explain every thing. https://stackoverflow.com/questions/43422932/async-await-always-returns-promise – Ralph Sachi Mar 10 '18 at 08:43
  • How abt this? var Person = function() { console.log("CALLED PERSON") }; Person.prototype.saySomething = async function() { console.log("saySomething PERSON") }; – Nadhas Dec 27 '18 at 10:50
2

It is possible to add an async function in the end of the prototype chain.

Please notice that this works well in nodejs 8.11.1+.

// lets start with defining some cool async function who takes the time and 
// awaits a promise 

async function someCoolAsyncFunction() {
    // this let will be returned after timeout in a different value.
    let coolStuff = 'still boring';

    // do something cool which takes time 
    await new Promise((resolve, reject) => setTimeout(() => {
        coolStuff = 'an epiphany';
        resolve();
    }, 1000))
    return coolStuff;
}

// Now let's define the 'regular' prototype chain with it's boring functions.

function Person(p) { 
     this.constructorPropery = p;
     return this;
}

Person.prototype.notAsync = function() {
     // do something regular in the prototype chain
     console.log("Let's build some ",this.constructorPropery)
     this.kindOfPerson = 'Regular and boring'; 
     return this;   
}

// And now, lets add an async function to this chain

Person.prototype.someAsyncFunction = async function() {
    // you will still have access to 'this' in this function as long as the
    // previous function in the prototype chain returnes 'this'
    console.log('I used to be someone ',this.kindOfPerson);

    // Now, this is our time to shine, lets await something cool
    this.lifeChangingEvent = await someCoolAsyncFunction();
    console.log('Until I had ',this.lifeChangingEvent);
    a.kindOfPerson = 'enlightened';
    console.log('and now I am ', a.kindOfPerson);
    return this;
}

So this will work:

new Person('charachter').notAsync().someAsyncFunction();

But this WILL NOT work:

new Person('charachter').someAsyncFunction().notAsync();

And if you really need the data in 'this' outside the prototype chain you can also do:

let myself = new Person('charachter').notAsync();
console.log('myself.kindOfPerson is: ',myself.kindOfPerson);
myself.someAsyncFunction(); 
console.log('myself.kindOfPerson now is: ',myself.kindOfPerson);

Be sure to remember which prototype is an async function for which function or use your own naming convection for that.

Adi Iluz
  • 21
  • 3