Unable to understand this

After once again reaching a point that I couldn’t complete questions on my own, I went back to redo the past sections. Now I’m at the functional programming section having a tough time solving this. The first time around I used slice because it didn’t change the code, but looking back I didn’t truly understand to solve it and that was the easy way out.

I see socialWindow is showing correct and workWindow and socialWindow are having issues, but I’m not sure how to remove 'Vimeo' in in the middle of the array and to keep 'Vine' by tweaking the slice function. Same goes for 'Work mail

The functions calling on each other may be my problem. I don’t know. .join(workWindow.tabClose(1).tabOpen()) is tough for me to wrap my head around. I don’t know why.

   **Your code so far**

// tabs is an array of titles of each site open within the window
var Window = function(tabs) {
 this.tabs = tabs; // We keep a record of the array inside the object
};

// When you join two windows into one window
Window.prototype.join = function (otherWindow) {
 this.tabs = this.tabs.concat(otherWindow.tabs);
 return this;
};

// When you open a new tab at the end
Window.prototype.tabOpen = function (tab) {
 this.tabs.push('new tab'); // Let's open a new tab for now
 return this;
};

// When you close a tab
Window.prototype.tabClose = function (index) {

 // Only change code below this line AKA slice(start, end before this position)

 var tabsBeforeIndex = this.tabs.splice(0, index); // Get the tabs before the tab
 var tabsAfterIndex = this.tabs.splice(index + 1); // Get the tabs after the tab

 this.tabs = tabsBeforeIndex.concat(tabsAfterIndex); // Join them together

 // Only change code above this line to add "Vine" and "Work mail" AKA videoWindow and workWindow

 return this;
};

// Let's create three browser windows
var workWindow = new Window(['GMail', 'Inbox', 'Work mail', 'Docs', 'freeCodeCamp']); // should be 'GMail', 'Work mail', 'Docs', 'freeCodeCamp', 'new tab'
var socialWindow = new Window(['FB', 'Gitter', 'Reddit', 'Twitter', 'Medium']); // 
var videoWindow = new Window(['Netflix', 'YouTube', 'Vimeo', 'Vine']); // should be 'Netflix', 'YouTube', 'Vine'

// Now perform the tab opening, closing, and other operations
var finalTabs = socialWindow
 .tabOpen() // Open a new tab for cat memes
 .join(videoWindow.tabClose(2)) // Close third tab in video window, and join
 .join(workWindow.tabClose(1).tabOpen());
console.log(finalTabs.tabs);
   **Your browser information:**

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.192 Safari/537.36.

Challenge: Understand the Hazards of Using Imperative Code

Link to the challenge:

I wouldn’t say using slice here is something bad and an easy way out. splice is tricky, as it’s modifying original array, and it can be hard to keep in mind how exactly splice changes the array.

Print to console how this.tabs looks after the first splice, this should help with figuring out what needs to change.

slice is the right method to use and using splice is causing the test to fail because it is destructive. The way splice is being used here is exactly how you would, and should use slice, splice takes longer than slice to do as well so if you can achieve the same result with same number of function calls to either than slice is better, that being said if you want to use splice to pass than it would like this

var tabsBeforeIndex = this.tabs.splice(0, index); // Get the tabs before the tab
var tabsAfterIndex = this.tabs.splice(1); // Get the tabs after the tab

If you want to pass the challenge with splice instead of slice, your code needs a small modification:

 var tabsBeforeIndex = [...this.tabs].splice(0, index); 
 var tabsAfterIndex = [...this.tabs].splice(index + 1); 

By spreading the tabs into a new array, the original array remains untouched. The above though is essentially the same as

 var tabsBeforeIndex = this.tabs.slice(0, index); 
 var tabsAfterIndex = this.tabs.slice(index + 1);

So, .slice is the best way to solve this challenge.


This is called “chaining”:

  • take the workWindow and use .tabClose(1) on it
  • take the result of that and use tabOpen() on it
  • finally, .join the result of that with whatever is before the dot of .join

Chaining creates a new value at each stop such as

["the array is a value"].map('this is a different value').filter('this is also a different value');
//the array was the original value and then you created
// a new value with `map` and on this new value you called
// `filter` creating the final value, and these were all non 
//destructive which is why each step is a new value and this 
//avoids side effects 

While it is true that this approach is non-destructive the performance of

 var tabsBeforeIndex = [...this.tabs].splice(0, index); 
 var tabsAfterIndex = [...this.tabs].splice(index + 1);

this would be unnecessarily slower, and I think the best non-destructive approach would be

const this.tabs = this.tabs.slice(0, index).concat(this.tabs.slice(index + 1))
//this ends up being destructive do to the reassignment, and I 
//should learn to read more throughly 😅

although I actually read the problem better and seeing my own solution I feel a bit silly as it is reassigns this.tabs so there is little reason to not do it destructively and therefore I think the best solution would be

this.tabs.splice(index, 1);

Just took two weeks off from coding and now taking a look again. I guess I’m just concerned about my understanding of this problem. I would’ve thought the solution with just splice should be more obvious to me, but I can’t wrap my head around it.

I wrote it out just now and this is what I’m seeing based on the existing splice methods

var finalTabs = socialWindow // creates 'FB', 'Gitter', 'Reddit', 'Twitter', 'Medium'
  .tabOpen() // creates 'new tab'
  .join(videoWindow.tabClose(2)) // closes 'vimeo' and 'vine'
  .join(workWindow.tabClose(1).tabOpen()); // closes 'inbox', 'Work mail', 'Docs', 'freeCodeCamp', adds new tab and join the rest
console.log(finalTabs.tabs);

Is there just no way to tweak the numbers in splice()? That’s what I would’ve thought would be possible

One of the big ideas in this challenge is that using slice is preferred over splice because slice does not create side effects. You can solve this with splice if you are careful, though.


I’m not sure why you are trying to change that part of the code?

Well it wasn’t mentioned that I should use slice so I thought I’d make sure I understand how to use splice correctly first. I actually just saw @caryaharper’s suggestion, but I didn’t solve it on my own that way (sadly).

Seems I didn’t notice that
var tabsAfterIndex = this.tabs.splice(1);
would continue from the index from ‘tabsBeforeIndex’. I had thought it’d just take Netflix rather than take Vine. I knew I was supposed to keep Vine. I also knew it was correctly removing Vimeo

It doesn’t. The ‘big idea’ is that the array is modified by splice.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice

This line

  var tabsBeforeIndex = this.tabs.splice(0, index); // Get the tabs before the tab

removes the the elements from 0 to index-1 from the array and assigns them to tabsBeforeIndex.

Ok so it continues off of the adjusted array correct?

I understand it is modified

In essence, the splice does

  var tabsBeforeIndex = this.tabs[0 : index - 1]; // Get the tabs before the tab
  this.tabs = this.tabs[index : end]; // Strip out first tabs

This code doesn’t quite work, but that’s the basic idea.

I understand it’s modified I’m just pointing out that the reason this works is because it’s going off of the adjusted array, correct?

I get the big idea, I’m just asking about the alternative solution with splice

I’m not sure what you mean by ‘going off the adjusted array’. The array is adjusted if you want to use splice. This means that you need to adjust your indexing to account for this fact. No matter what you do, you use the modified/adjusted array, so your logic needs to reflect that.

Ok never-mind maybe it’s just something that makes sense in my head. Unfortunately I use different regular grammar in this forum as I’m still learning so sometimes it doesn’t make sense to you guys or to me what you’re saying

Just curious is there a difference between adjusted and modified?

Modified is just a more common word for changing a variable, object, array, etc in my experience. Adjustment implies a small change to me, and pulling out entries and reindexing is not a small change to me.