Shuffle Method - work the first time, failed the second time

Hey guys!

I just finished the Build a Library project and I tried to create the shuffle() method for the CD class.
However, a funny bug happened: the method worked the first time perfectly, but the second time it delivered empty arrays…

Check out my initial code (Media super class, CD class):

// creating the Media superclass to contain Book, CD and Movie classes class Media { // defining the constructor constructor(title) { typeof title === 'string'? this._title = title: console.log('Use a string to create a new valid object'); this._isCheckedOut = false; this._ratings = []; }; // defining getter and setter functions get title() { return this._title; } get isCheckedOut(){ return this._isCheckedOut; } get ratings() { return this._ratings; } }; // defining CD class class CD extends Media { constructor(artist, title, songs) { super(title); typeof artist === 'string'? this._artist = artist: console.log('Invalid artist name'); this._songs = songs; } // defining getters for CD class get artist() { return this._artist; } get songs() { return this._songs; } // defining new methods for CD class shuffle() { let remainSongs = this._songs; let shuffledSongs = []; let selector; while(remainSongs.length > 0) { selector = Math.floor(Math.random() * remainSongs.length); shuffledSongs.push(remainSongs[selector]); remainSongs.splice(selector, 1); } return shuffledSongs; } }; //Try it out const eyeOfTiger = new CD('Tina Turner', 'Eye Of The Tiger', ['track0', 'track1', 'track2', 'track3', 'track4', 'track5', 'track6', 'track7']); let shuffle1 = eyeOfTiger.shuffle(); let shuffle2 = eyeOfTiger.shuffle(); console.log(shuffle1); console.log(shuffle2);

Do you know why this happens and what is the best practices and solution for this case?
I believe it has something to do with this keyowrd inheritance or similar

1 Like

Hi, by doing this in your code on line 38:

let remainSongs = this._songs;

you didn’t copy the this._songs array, but just assigned it to the variable remainSongs, and by running remainSongs.splice() you are actually modifying your original array, stored in this._songs. So, when you try to call the shuffle method for the second time it returns an empty array because this._songs is empty.
To solve the problem, you can use a spread operator to assign a copy of this._songs to remainSongs variable:

let remainSongs = [...this._songs];

This way, the original array stored in this._songs will remain intact no matter how many times the shuffle method is called.

1 Like

Hey Janetrish,

Thank you for your help!

I read something about this keyword and reference values and I think it has something to do with it.
But I still don’t quite understand what it means yet!

You’re right, there are two ways how JavaScript stores data in memory. Primitive data types (e.g. number, string, boolean, null, undefined) are stored by value, complex types (e.g. array, object) - by reference. It is not something specific to this keyword, it depends on the type of data you store in a variable.

In your code this._songs is an array, which is not a primitive type, hence it was stored by reference. It means that when you assigned this._songs to remainSongs, there was no copy of the original array created in the memory. Another simple example:

let numbers = [1, 2, 3, 4]
let newNumbers = numbers

console.log(numbers) // [ 1, 2, 3, 4 ]
console.log(newNumbers) // [ 1, 2, 3, 4 ]

Both variables point to the same place in memory, that’s why by modifying one of them you will actually modify both.

console.log(numbers) // [ 1, 2, 3, 4, 5 ]
console.log(newNumbers) // [ 1, 2, 3, 4, 5 ]

I would recommend you to watch this video to understand the topic better: Reference Vs Value In JavaScript - YouTube

1 Like