Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript Object-Oriented JavaScript (2015) Constructor Functions and Prototypes Methods with Prototypes

Does arrow function syntax works for prototype?

I tried to use arrow function syntax like this:

Dice.prototype.roll = () => {
  const randomNumber = Math.floor(Math.random() * this.sides) + 1;
  return randomNumber;
}

and got no error but NaN as a result. Could you explain why?

Thank you!

Rogier Nitschelm
seal-mask
.a{fill-rule:evenodd;}techdegree
Rogier Nitschelm
iOS Development Techdegree Student 5,461 Points

That is because the 'this' is interpreted as 'undefined' because an arrow function automatically binds the context . It is trying to multiply the outcome from Math.random() with undefined. And undefined is not a number (NaN) :). Instead of using an arrow function, you should use a regular function(). Remember that even though an arrow function looks more concise its not an alternative to the regular function.

Dice.prototype.roll = function() {
  const randomNumber = Math.floor(Math.random() * this.sides) + 1;
  return randomNumber;
}

Also if you visit babeljs.io you can even see for yourself what happens behind the scenes by pasting your code in the online compiler.

Thank you, Rogier! But why in this case, if I use the arrow syntax in the constructor directly, like this:

function Dice(sidesNum) {
  this.sides = sidesNum;
  this.roll = () => {
    const randomNumber = Math.floor(Math.random() * this.sides) + 1;
    return randomNumber;
  }
}

everything works perfect?!

ywang04
ywang04
6,762 Points
Dice.prototype = {
  roll: () => {
    return Math.floor(Math.random() * this.sides) + 1;
  }
};

This works fine.

2 Answers

Rogier Nitschelm
seal-mask
.a{fill-rule:evenodd;}techdegree
Rogier Nitschelm
iOS Development Techdegree Student 5,461 Points

That is because the arrow function inside the regular function is bound to the same context that contains the 'this.sides'. It is a fairly hard topic to grasp, but there are alot of good resources on it online.

Here is a great article describing when not to use the arrow function. It also has a good explanation on your example:

https://rainsoft.io/when-not-to-use-arrow-functions-in-javascript/

Thank you Rogier!!! That great answer helped me!

If you want to use features from ES6 and beyond anyway, you might want to have a look at classes. This way you can transform something like

function Monster(name) {
  this.name = name;
  this.health = 100;
}
Monster.prototype.takeDamage = function () {
    this.health--;
  }

into the following:

class Monster {
    constructor(name) {
        this.name = name;
        this.health = 100;
    }
    takeDamage() {
        this.health--;
    }
}

The method called constructor corresponds to the old constructor function and any methods you define are added to the prototype. You still create new instances the same way as before, namely new Monster('fancy name').