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 Making the UI Work

romankozak2
romankozak2
5,782 Points

Trouble understanding the .play() and .stop() in the Playlist.prototype.play and Playlist.Prototype.stop functions.

The .play() and .stop() in the Playlist.prototype.play function confuse me in the playlist.js file. Is he using the prototype method from the Song constructor function? If so, I thought only instances of a constructor function inherit the methods? How can a prototype method from the Playlist constructor function call a method from the Song constructor function without prototypal inheritance (I hope that makes sense)? Isn't the .play() and .stop() prototype methods from the Song constructor function in the scope of that particular constructor function, and not global and accessible in the scope of another constructor function? And it's also very confusing because the prototype function that currentSong.play() is being called in is also Playlist.prototype.play. I'm mixing the plays up.

Lastly, then, how does the .play() in the Playlist.prototype.play function know which .play() to choose? That may be answered more clearly if the part of my question above is answered. Thanks!

1 Answer

geoffrey
geoffrey
28,736 Points

Hey there, you ask if It uses the play method from the Song constructor when you see this inside the Playlist constructor I guess:

Playlist.prototype.play = function() {
  var currentSong = this.songs[this.nowPlayingIndex];
  currentSong.play();
};

Yes It does, it actually calls the play method defined inside the Song constructor.

Why ? Because as you notice, the method is called on an object called currentSong, the currentSong is an object you get thanks the current index of the PlayList object you set.

To see it, check the Playlist constructor

function Playlist() {
  this.songs = []; // this array is then filled with all the song objects we create inside the app.js file
  this.nowPlayingIndex = 0; // this property is set according the currentSong (change when we push the next and previous button as an exemple).
}

As you see, each playlist object comes with an array with all the songs objects and a property with the current song (its index in the array). But when you create this object, this array is firstly empty, so you need to fill that array later on.

To fill the playlist object created in the app.js file. Andrew first creates all the songs (which are obviously objects create based on the Song the constructor).

Check the code below to see it.

var hereComeTheSun = new Song("Here comes the Sun","The Beatles","2:54");
var walkingOnSunshine = new Song("Walking on Sunshine", "Katrina","3:54");

Not only he sets the name of the songs and their duration, but as defined in the constructor these songs have a property (isPlaying) set by default to the boolean false. So they all have this property and as well the methods defined with the help of the prototype.

One of these methods is the play method... (the one you are talking about, which is called inside the play method of the playlist, but called on the song object ! )

Song.prototype.play = function() {
  this.isPlaying = true;
};

After that, as the songs are created, Andrew adds all the songs to the songs array which is inside the Playlist object (which is empty at first) thanks the add method of the playlist consctructor created previously.

Playlist.add(hereComeTheSun);
Playlist.add(walkingOnSunshine);

// This actually fills the songs array in the Playlist objects with the added songs objects. Remember they have their properties and methods ( such as the play method and etc...)

This add method as you might have seen simply fills the array thanks the native Javascript push method.

So instead of having an empty array within the Playlist object, we now have a Playlist object with songs objects filling our song array.

Do not forget that these songs we pushed have as well as I already wrote above a property called "isPlaying" set to false by default and methods such as stop and play.

As you have probably seen, some others methods are available within the Playlist constructor as Andrew creates them with the Playlist constructor. One of them is as an exemple the next method.

And what happens is that when we click the next button, the next method is called.

Because of that, the nowPlayingIndex property inside our Playlist object is incremented.... and thus the currentSong is changed !

At first the nowPlayingIndex is at 0 when the playlist is created.

So based on the songs we added above at first the currentSong variable defined in the play method of the playlist object referes to "here Come the Sun". Because the current Index is 0 at first.

As litteral object it looks this way

{title: "Here comes the Sun",
 artist: "The beatles",
 duration: "2:54", 
 isPlaying: true,
 play: function(){         /** **/

  this.IsPlaying: true;
  },
  stop:function(){
  this.isPlaying = false;
  }
}

/*
  var currentSong = this.songs[this.nowPlayingIndex];
  currentSong.play(); calls the play method on the song object
*/

So when we push the next button, It's the next song stored in the song array of the Playlist Object that 's stored in the currentSong variable, and the methods of this object stored inside the currentSong variable can be called.

So even if both objects have a play method this isn't an issue, because when you call the play method on the currentSong variable, you call the play method of the current song* object !

I hope It makes more sense.

romankozak2
romankozak2
5,782 Points

This was WONDERFUL! Thank you for breaking it down this way. Cheers!

geoffrey
geoffrey
28,736 Points

you welcome :)

Dylan Macnab
Dylan Macnab
24,861 Points

Great answer! I watched the videos twice and still didn't totally understand how this code works. Andrew glossed over a lot of details in this project and I think you filled in the gaps nicely.

A couple key things I struggled to understand in Andrew's explanation is how the Playlist.songs array is used as a container for the song objects. And related to that, how the currentSong.play() and currentSong.stop() are methods of the song objects, which are different from the .play() and .stop() methods attached to the playlist object. It tripped me up that we were using methods from the song object in the playlist.js file. I guess I just assumed they were methods of the playlist object and not the song object.

Thanks again!