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 Playlist Project

Kevin Bullis
Kevin Bullis
13,770 Points

How I figured out where play() and stop() are defined

Several people, myself included, got confused about where play() and stop(), which are used in the playlist.js file, are defined. Some of the other answers in this discussion try to explain this, but I couldn't understand them.

To figure it out, I first pasted all of the javascript into a single file. Then I included comments to figure out what came from where.

The key is that instances of Playlist are made up of instances of Song.

So when you write:

currentSong.play();

This is equivalent to writing:

hereComesTheSun.play(), 

which is equivalent to writing :

new Song("Here Comes the Sun", "The Beatles", "2:54").play()  

Which is equivalent to

Song.prototype.play()

At least, that's what I think is going on.

Here's the entirety of the js, with the comments I wrote to figure it out.

//Song constructor. Used to create objects that have a title, artist, duration, and isPlaying status.

function Song(title, artist, duration) {
  this.title = title;
  this.artist = artist;
  this.duration = duration;
  this.isPlaying = false;
}

//Shared Song constructor prototypes. play() changes isPlaying to "true". stop() changes isPlaying to "false". toHTML() adds a list item to the ordered list in the index.html file. This list item is given the class "playing" if the play() function has been called. 

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

Song.prototype.stop = function() {
  this.isPlaying = false;
};

Song.prototype.toHTML = function() {
  var htmlString = '<li';
  if(this.isPlaying) {
    htmlString += ' class="playing"';
  }
  htmlString += '>';
  htmlString += this.title;
  htmlString += ' - '
  htmlString += this.artist;
  htmlString += '<span class="duration">'
  htmlString += this.duration;
  htmlString += '</span></li>';
  return htmlString;
};

//Playlist constructor stores an array of songs and an index number to access those songs.

function Playlist() {
  this.songs = [];
  this.nowPlayingIndex = 0;
}

// Shared Playlist constructor prototypes. 

//add() uses the push method to add a song to a Playlist instance, playlist (defined below). add() takes a parameter, (song). That comes from an instance of the Song constructor, which is created below. So, when you call the add(), you do this: add(new Song("Here Comes the Sun", "The Beatles", "2:54")). 
//The resulting array item looks like this:
// [ 
//    {
//    title: "Here Comes the Sun",
//    artist: "The Beatles",
//    duration: "2:54",
//    isPlaying: false
//  }
// ]

Playlist.prototype.add = function(song) {
  this.songs.push(song);
};

//play() first selects a song from the playlist array and stores this song in the variable currentSong. Remember that the song in the playlist is an instance of the Song constructor. So currentSong.play() is equivalent to hereComesTheSun.play(), which is equivalent to new Song("Here Comes the Sun", "The Beatles", "2:54").play()   So you're calling an instance of Song.prototype.play(). As you can see above, Song.prototype.play() sets isplaying to "true".

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

//just as currentSong.play() is equivalent to Song.prototype.play(), currentSong.stop() is equivalent to Song.prototype.stop() which sets isPlaying to false.

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

Playlist.prototype.next = function() {
  this.stop();
  this.nowPlayingIndex++;
  if(this.nowPlayingIndex === this.songs.length) {
    this.nowPlayingIndex = 0;
  }
  this.play();
};

Playlist.prototype.renderInElement = function(list) {
  list.innerHTML = "";
  for(var i = 0; i < this.songs.length; i++) {
    list.innerHTML += this.songs[i].toHTML();
  }
};


var playlist = new Playlist();

var hereComesTheSun = new Song("Here Comes the Sun", "The Beatles", "2:54");
var walkingOnSunshine = new Song("Walking on Sunshine", "Katrina and the Waves", "3:43");

playlist.add(hereComesTheSun);
playlist.add(walkingOnSunshine);

var playlistElement = document.getElementById("playlist");

playlist.renderInElement(playlistElement);

var playButton = document.getElementById("play");
playButton.onclick = function() {
  playlist.play();
  playlist.renderInElement(playlistElement);
}

Excellent explanation! Thanks

Daniel Nitu
Daniel Nitu
13,272 Points

THANK YOU! I've been struggling for quite a while to make sense of this. Your explanation really helped me out!

Michael Lauridsen
Michael Lauridsen
10,321 Points

Thank you! Couldn't figure it out on my own.

1 Answer

Chris Wiley
Chris Wiley
14,669 Points
currentSong.play();

This is called in the Song constructor

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

Then the Playlist constructor calls it in it's function while creating another play() method for itself.

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

The currentSong.play() sets the isPlaying to true and the Playlist.play() determines which song gets the true value.

I hope that helps.