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 Challenge Solution

that...or this? **Spoiler Alert** (Solution is discussed here)

Here is the solution

var Dice = function (sides) {

  this.sides = sides

  this.roll = function () {
    var randomNumber = Math.floor(Math.random() * this.sides) + 1
    return randomNumber
  } // roll fn

} // Dice Constr fn

var dice = new Dice(6)

But - I thought* that nested functions did not have access to the outer functions 'this' or 'arguments', so a 'that' had to be declared, like so:

var Dice = function (sides) {

  var that = this

  this.sides = sides

  this.roll = function () {
    var randomNumber = Math.floor(Math.random() * that.sides) + 1 // that
    return randomNumber
  } // roll fn

} // Dice Constr fn

var dice = new Dice(6)

* I may be imagining this, as I am at an awkward phase of my progression where I have looked at a lot of things now, but mastered little! Have I just put in an unnecessary bit of code??

Karolin Rafalski
Karolin Rafalski
11,368 Points

Inner functions can look 'up', outer functions cannot look 'down'.

In this case, this will work fine.

There are times where you may want to pass a different this to a function, to which you can create a variable 'that' (like you have) or use .bind() https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

Yes, I understand that an inner function can look 'up' or 'out' to see an outer function's properties (but not vice-versa), but the inner function cannot access the outer function's 'this', hence my confusion, because in my example, the inner function is accessing the outer functions 'this' with no problems.

3 Answers

Right, so the TL:DR is:

Constructors create a new object with 'this' bound to that object, so you can ignore the function in a constructor for nesting intents/purposes.

Thanks

Thomas Nilsen
Thomas Nilsen
14,957 Points

This can be confusing:

Here is a tiny example that shows a case where 'this' points to the wrong thing, and what can be done about it:

var obj = {
    prop: 'hello',
    func: function() {
        console.log(this.prop); //This works

        function sayHello() {
            console.log(this.prop); //In here - 'this' refers to the global object (ie. the window), and not our object. 
        }

        sayHello(); //prints undefined


        var sayHello2 = function() {
            console.log(this.prop);
        }.bind(this);

        sayHello2(); //Since we used bind, this also works.
    }
};

obj.func();

No I totally get it - if a function is inside a function, it loses access to the outer function's 'this'...

...but that is exactly why I am confused, because if you look at my example, that is what is happening; Dice is a function and inside that function is an anonymous function stored in dice.roll.

Unless the answer is something to do with Constructor functions not being treated as functions per se maybe?

Thomas Nilsen
Thomas Nilsen
14,957 Points

Yes - but you create a new instance using the new keyword. There is a couple of things that happens when you do.

This is taken from the mozilla-pages:

When the code new Foo(...) is executed, the following things happen:

  • A new object is created, inheriting from Foo.prototype.

  • The constructor function Foo is called with the specified arguments, and with this bound to the newly created object. new Foo is equivalent to new Foo(), i.e. if no argument list is specified, Foo is called without arguments.

  • The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)