Tell us what’s happening:
As I under the exercise, we’re supposed to apply making changes to a function that declare a certain action we want to happen without changing the global variable.
From previous lessons, I’ve gathered that a new variable must be created to perform the changes that cannot be made to the global variable AND the way to do this is to assign the information of the global variable. I’ve attempted to do this below but to no success.
I have a few questions:
Have I misinterpreted the lesson to be gained from the previous exercises?
Should I be using .slice() or .splice() or .push() methods to achieve the desired result?
If so, how am I misusing them?
Thank you for your assistance.
Your code so far
// the global variable
var bookList = ["The Hound of the Baskervilles", "On The Electrodynamics of Moving Bodies", "Philosophiæ Naturalis Principia Mathematica", "Disquisitiones Arithmeticae"];
/* This function should add a book to the list and return the list */
// New parameters should come before the bookName one
// Add your code below this line
function add (bookName) {
var bkGain = bookList;
return bkGain.push(bookName);
// Add your code above this line
}
/* This function should remove a book from the list and return the list */
// New parameters should come before the bookName one
// Add your code below this line
function remove (bookName) {
var bkRmov = bookList;
if (bkRmov.indexOf(bookName) >= 0) {
return bkRmov.splice(0, 1, bookName);
// Add your code above this line
}
}
var newBookList = add(bookList, 'A Brief History of Time');
var newerBookList = remove(bookList, 'On The Electrodynamics of Moving Bodies');
var newestBookList = remove(add(bookList, 'A Brief History of Time'), 'On The Electrodynamics of Moving Bodies');
console.log(bookList);
Your browser information:
User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36
.
Link to the challenge:
https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/functional-programming/refactor-global-variables-out-of-functions
So this is the list of Array prototype methods:
The first set, the ones listed under the Mutator Methods header, they all mutate an existing array. push
and splice
are mutator methods.
Using push
or splice
on the array that the global variable references will modify that globally-available array (this is generally bad for a number of reasons).
But using slice
copies a slice of the array (the slice can be the same size as the original array). It doesn’t mutate the original array (note slice
& other non-mutating methods will generally make your life easier in JS, things that do not mutate are much easier to reason about)
I have used a non-mutating method with bookList and created copies of bookList in order to use mutating methods to add and remove elements without affecting the origin array.
However, I am not satisfying the challenge and I don’t know how else to proceed. I think I’m doing everything that would lead to a correct solution, but obviously not. Could someone point out where I err?
// the global variable
var bookList = ["The Hound of the Baskervilles", "On The Electrodynamics of Moving Bodies", "Philosophiæ Naturalis Principia Mathematica", "Disquisitiones Arithmeticae"];
/* This function should add a book to the list and return the list */
// New parameters should come before the bookName one
// Add your code below this line
function add (bookName, bkGain) {
bkGain = bookList.slice(0).push(bookName);
return bkGain;
// Add your code above this line
}
/* This function should remove a book from the list and return the list */
// New parameters should come before the bookName one
// Add your code below this line
function remove (bookName, bkRmov) {
bkRmov = bookList.slice(0);
if (bkRmov.indexOf(bookName) >= 0) {
return bkRmov.splice(0, 1, bookName);
// Add your code above this line
}
}
var newBookList = add(bookList, 'A Brief History of Time');
var newerBookList = remove(bookList, 'On The Electrodynamics of Moving Bodies');
var newestBookList = remove(add(bookList, 'A Brief History of Time'), 'On The Electrodynamics of Moving Bodies');
console.log(bookList);
var newBookList = add(bookList, 'A Brief History of Time');
Your code means for that, you are assigning the value 5
to newBookList
. Your code always returns a number for the add
function.
Edit: look at this:
This is the function being called:
add(bookList, 'A Brief History of Time');
So it takes
- an array of books and
- the name of a book.
The array of books that goes into that particular call happens to be the global one, but it could be any array. But your definition of the function:
function add (bookName, bkGain) {
bkGain = bookList.slice(0).push(bookName);
return bkGain;
}
So it asks you.to put the new argument before the existing one (the name of the book), but you have put it after.
It asks you not to refer to anything outside the function, but you refer to the global bookList
. You are supposed to be using the argument you added (which is an array of books) — if the global bookList is passed to the function then that gets used.
It’s not working and I’ve changed my coding to match explicitly (I believe) the directions of the challenge.
I think my issue is in the order in which I am using variables and perhaps my incorrect ordering of them causes them to lose valence AND/OR I am still using mutating variables in the wrong manner, affecting bookList when that is supposed to be immutable.
My code is below.
// the global variable
var bookList = ["The Hound of the Baskervilles", "On The Electrodynamics of Moving Bodies", "Philosophiæ Naturalis Principia Mathematica", "Disquisitiones Arithmeticae"];
/* This function should add a book to the list and return the list */
// New parameters should come before the bookName one
// Add your code below this line
function add (bkGain, bookName) {
var bkGain = bookList;
add(bkGain.slice(0), bkGain.push(bookName));
return bkGain;
// Add your code above this line
}
/* This function should remove a book from the list and return the list */
// New parameters should come before the bookName one
// Add your code below this line
function remove (bkRmov, bookName) {
var bkRmov = bookList;
remove(bkRmov.splice(1, 1), bookName);
return bkRmov;
// Add your code above this line
}
var newBookList = add(bookList, 'A Brief History of Time');
var newerBookList = remove(bookList, 'On The Electrodynamics of Moving Bodies');
var newestBookList = remove(add(bookList, 'A Brief History of Time'), 'On The Electrodynamics of Moving Bodies');
console.log(bookList);
No, this is more wrong. You are not following the directions of the challenge.
Declare function arguments - any computation inside a function depends only on the arguments, and not on any global object or variable.
You are writing a function that takes an array (any array!) and a string (any string!) and returns a new array that looks like the array you put into the function with the string added to the end.
To simplify this, can you write a function that takes one argument (an array) and returns a copy of that array? So it would be:
function copyBooklist(listOfBooks) {
// return a copy of the list of books
}
I’m not passing the test, but I’m starting to understand the ethics behind Functional Programming. So, below I’ve created new variables within their own function that add or remove book titles. As i understand it, I am creating a local scope to complete tasks that utilize content of the global scope (through copying it), but do not alter the global scope. All alteration takes place within the local scope.
That said, I don’t know what I’m doing wrong and need some guidance in the right direction. Thank you!
// the global variable
var bookList = ["The Hound of the Baskervilles", "On The Electrodynamics of Moving Bodies", "Philosophiæ Naturalis Principia Mathematica", "Disquisitiones Arithmeticae"];
/* This function should add a book to the list and return the list */
// New parameters should come before the bookName one
//Create new arguments for add function
function add (copyBookList, bookName) {
//Create new variable to store changes to copied array
var listTwo = copyBookList.slice(0, copyBookList.length);
listTwo.push(bookName);
return listTwo;
// Add your code above this line
}
/* This function should remove a book from the list and return the list */
// New parameters should come before the bookName one
// Create arguments for remove function
function remove (copyBookList, bookName) {
//Use let to invoke previously create variable to store new changes to copied array
let listTwo = copyBookList.slice(0, copyBookList.length);
if (listTwo.indexOf(bookname) >= 0) {
listTwo.splice(listThree.indexOf(bookName), 1)
return listTwo;
console.log(listTwo);
// Add your code above this line
}
}
console.log(listTwo)
var newBookList = add(bookList, 'A Brief History of Time');
var newerBookList = remove(bookList, 'On The Electrodynamics of Moving Bodies');
var newestBookList = remove(add(bookList, 'A Brief History of Time'), 'On The Electrodynamics of Moving Bodies');
console.log(bookList);
It’s a slight shift in thinking, I get why it seems a bit alien. Keep at it though, as JS generally tends to be a lot easier once it clicks — it becomes far easier to understand what is happening in a program, it’s much easier to test.
function add (copyBookList, bookName) {
var listTwo = copyBookList.slice(0, copyBookList.length);
listTwo.push(bookName);
return listTwo;
}
So this works! You’ve got it, but are a few things to maybe make it easier to grok
- if you miss the last argument off
slice
, it automatically slices to the end of the list
- if you miss the first argument off as well, it assumes you want to spice form the start of the list.
- the argument to the function isn’t a copy of anything, it’s just an array of books (a bookList). It’s just the name of the argument, nothing to do with any external variables like that global
bookList
.
function add (bookList, bookName) {
var copyBookList = bookList.slice();
copyBookList.push(bookName);
return copyBookList;
}
But you’re still doing this quite verbose make a copy, push to the copy, and that doesn’t return the array, so you need to return on the next line.
Amongst the non-mutating methods for arrays, there’s one called concat
which lets you join arrays together, or add values to an array. And it returns a new updated array. So
function add(bookList, book) {
// Return a new array with the book added:
return bookList.concat(book);
}
There is a method called filter
that will allow you to remove in kinda the same way, but it’s a little more involved (and the functional part of the FCC curriculum has a section on it). This will not make as much sense as concat
, but just for completeness:
function remove(bookList, bookToRemove) {
// Return a new array with books that are not
// the one you want to remove
return bookList.filter(book => book !== bookToRemove);
}
1 Like