Function call using previous value? - javascript

// The global variable
var bookList = ["The Hound of the Baskervilles", "On The Electrodynamics of Moving Bodies", "Philosophiæ Naturalis Principia Mathematica", "Disquisitiones Arithmeticae"];
// Change code below this line
function add (bookName, test) {
console.log('t', bookName)
let newB = bookName;
newB.push(test)
return newB;
// Change code above this line
}
// Change code below this line
function remove (bookName) {
var book_index = bookList.indexOf(bookName);
if (book_index >= 0) {
bookName.splice(book_index, 1);
return bookName;
// Change 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(newBookList, newerBookList, newestBookList)
console.log(bookList);
t [ "The Hound of the Baskervilles", "On The Electrodynamics of Moving Bodies", "Philosophiæ Naturalis Principia Mathematica", "Disquisitiones Arithmeticae" ] t [ "The Hound of the Baskervilles", "On The Electrodynamics of Moving Bodies", "Philosophiæ Naturalis Principia Mathematica", "Disquisitiones Arithmeticae", "A Brief History of Time"
How come there is the two strings; "A Brief History of Time" and "A Brief
History of Time" is it saving the value and using it again? How would it
remember that there was a brief history in time in the last function call?
The function call in the third global variable is add(bookList, 'A Brief
History of Time') so what is happening?
If you don't understand what I am saying, basically, I am trying to fix the
add() function and it's working but it's run twice because it's assigned to
two variables and the problem is that in the newestBookList, the add()
function added the string, but it added the string to the array that I made
before in the add() function.

By the way you have named your variable in the line: let newB = bookName;, this line of code is not doing what you think it's doing. It is not creating a new instance of bookName, it is just assigning to newB the existing array reference passed in on the bookName parameter, which is bookList.
Since you continue to pass in bookList and do not get a new array reference with something like [...bookName] or bookName.slice(), it keeps using that same array with each subsequent call. So it will continue to push values onto the same array. That's why you're getting the output you're getting.
One example of how you can return a new array reference each time is like so:
function add (bookName, test) {
console.log('t', bookName)
let newB = bookName.slice(); // generates a new array with the same elements
newB.push(test)
return newB;
}

The problem is that when you reassign your array in the add function your just passing on the array reference. This causes the original array to be
If you intent to use your bookList as an initial state and add and remove to change and return the new state. Another problem I see in your code is that on your remove you are also changing the original array with the splice function. If you intent to follow this approach I recommend the following changes to make sure you're not overriding the original state.
// The global variable
const initialBookList = ["The Hound of the Baskervilles", "On The Electrodynamics of Moving Bodies", "Philosophiæ Naturalis Principia Mathematica", "Disquisitiones Arithmeticae"];
function add(prev, bookName) {
return [...prev, bookName];
}
function remove(prev, bookName) {
const idx = prev.indexOf(bookName);
if (idx === -1) return [...prev];
return [
...prev.slice(0, idx),
...prev.slice(idx + 1, prev.length),
];
}
const bookList1 = add(initialBookList, 'A Brief History of Time');
const bookList2 = remove(initialBookList, 'On The Electrodynamics of Moving Bodies');
var bookList3 = remove(add(initialBookList, 'A Brief History of Time'), 'On The Electrodynamics of Moving Bodies');
console.log({
initialBookList,
bookList1,
bookList2,
bookList3,
})

Related

Using ForEach and getting repeated elements in JavaScript

What I am trying to do is with an input add words into an array, then as you add the words I want them to be displayed in a list. So I did a function to render the list, and used a for each, then used that function inside the function that push the words into the array. The thing is that when you add the words the for each executes and duplicates all the words.
if you add tree as a word you get the output: tree
if you add rabbit you get the output : tree, tree, rabbit
lets say you want to add falcon and you get: tree, tree, rabbit, tree, tree, rabbit, falcon
Here is the code
const renderPass = function (array, location) {
array.forEach((element) => {
let html = `<li class="k">${element}</li>`;
location.insertAdjacentHTML("afterbegin", html);
});
};
const savingKeyWords = function (e) {
e.preventDefault();
keyWords.push(keyWord.value);
renderPass(keyWords, listOfKeys);
console.log(keyWords);
clear(keyWord);
};
could you help me with this??
That is because you seem to be using the same array defined in the global context over and over on every invocation.
Just create a new array when ever saving keywords is invoked.
const savingKeyWords = function (e) {
let keyWords = [];
e.preventDefault();
keyWords.push(keyWord.value);
renderPass(keyWords, listOfKeys);
console.log(keyWords);
clear(keyWord);
};
I think 'keyWords' has to be replaced with 'keyWord.value' in here:
renderPass(keyWords, listOfKeys);
And
const renderPass = function (keyWord, location) {
let html = `<li class="k">${keyWord}</li>`;
location.insertAdjacentHTML("afterbegin", html);
};
I hope this will be helpful for you. Thanks

Uncaught TypeError: quotesData[currentQuote] is undefined

i try to build a simple javasciprt random quote app but in the very first test of my code i saw this in console : Uncaught TypeError: quotesData[currentQuote] is undefined
showquote http://127.0.0.1:5500/js/main.js:31
http://127.0.0.1:5500/js/main.js:37
this is js code source :
quotesData = [{
quote: `There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle.`,
name: 'Albert Einstein '
},
{
quote: `Good friends, good books, and a sleepy conscience: this is the ideal life.`,
name: 'Mark Twain'
},
{
quote: `Life is what happens to us while we are making other plans.`,
name: 'Allen Saunders '
},
{
quote: `It's not the load that breaks you down, it's the way you carry it.`,
name: 'Lou Holt'
},
{
quote: `Try not to become a man of success. Rather become a man of value.`,
name: 'Albert Einstein '
},
]
/* important variables */
const currentQuote = quotesData[0];
const quoteText = document.getElementById('quote');
const quotebtn = document.getElementById('q-btn');
const quotepan = document.getElementById('q-span');
/* this function is for show the quote and author name */
function showquote() {
quoteText.innerText = quotesData[currentQuote].quote;
quotespan.innerText = quotesData[currentQuote].name;
currentQuote++;
};
/* this function is for change the quote and author name with evrey click */
quotebtn.addEventListener('click', showquote())
currentQuote isn't an array index, it's an element of the array.
You need to set it to 0, and it can't be const if you want to increment it.
let currentQuote = 0;
Also, the second argument to addEventListener should be a reference to a function. You're calling the function immediately instead of saving it as a listener.
quotebtn.addEventListener('click', showquote);
After you increment currentQuote, you need to check if you've reached the end of the array and wrap around. You can do this using the modulus operator.
function showquote() {
quoteText.innerText = quotesData[currentQuote].quote;
quotespan.innerText = quotesData[currentQuote].name;
currentQuote = (currentQuote + 1) % quotesData.length;
};
A couple problems with your code -
Replace quotebtn.addEventListener('click', showquote()) with quotebtn.addEventListener('click', showquote) because otherwise you are passing the return value of showquote to the function.
currentQuote is an object which cannot be passed as an index. You need to set currentQuote to 0 so you can increment it.
This is still not random quotes, but it solves your problems.
currentQuote is a constant variable - which means you can't increment it because ++ is actually just syntactic sugar for += 1 which in itself is syntactic sugar for currentQuote = currentQuote + 1. Change it to let.
TIP:
Do not mix ES5 and ES6. Old functions should only be used when access to the this keyword is needed. Otherwise, stick to one version for semantic purposes.

Nested loop (FOR) with IF statement inside 2nd for print just one result

Basically I have 2 arrays, one with some code and another with codes and relative description, what I need to do is match the codes and print the description but my code (apparently) stops at the first loop of the inner FOR (I've attaches a screenshot to understand better).
If I remove the IF statement from the code it prints the counters of the 2 for as it should be.
for (x=0; x<causeoferrorlength; x++)
{
document.getElementById("mdataresult").innerHTML += "x "+causeoferrorsplit[x]+"</br>";
for(k=0; k<78; k++)
{
if ( causeoferrorsplit[x] === gbrucausesoferror[k][0] )
{
document.getElementById("mdataresult").innerHTML += "k "+gbrucausesoferror[k][0]+"</br>";
}
}
}
I have no errors from the console but it isn't printing as expected.
This is probably better handled in a declarative way versus imperative. It will be shorter and easier to reason about.
Given you're using two arrays, and that the codes in the first array will always be found somewhere in the second array:
let causes = ["001", "003", "005"];
let codes = [
["001","Earthquake"],
["002","Sunspots"],
["003","User Error"],
["004","Snakes"],
["005","Black Magic"]
];
let results = causes.map( cause => codes[ codes.findIndex( code => code[0] === cause ) ][1] );
console.log(results); // ["Earthquake", "User Error", "Black Magic"]
What's happening here? We're mapping the array of potential causes of error (the first array) to a list of descriptions taken from the second array.
Array.map takes a function that is invoked once with each array member. We'll call that member 'cause'.
Array.findIndex takes a function that is invoked once for each array member. We'll call that member 'code'.
For each 'cause' in causes we find the index in codes where the first array value is equal to the cause, then return the second array value, the description.
If you have the ability to change the second array to an object, then this gets way simpler:
let causes = ["001", "003", "005"];
let codes = {
"001":"Earthquake",
"002":"Sunspots",
"003":"User Error",
"004":"Snakes",
"005":"Black Magic"
};
let results = causes.map( cause => codes[cause] );
console.log(results); // ["Earthquake", "User Error", "Black Magic"]

Why does map work differently when I return an array instead of some primitive in the callback function?

Script
var companies=[
{name:'Vicky',category:'Devdas',start:1993,end:2090},
{name:'Vikrant',category:'Devdas',start:1994,end:2019},
{name:'Akriti',category:'mental',start:1991,end:2021},
{name:'Dummy',category:'dummyCategory',start:1995,end:2018},
{name:'Dummy 1',category:'dummyCategory',start:1993,end:2029}
];
var mappingComp=companies.map(company=>{company.start+10;return company});
console.log("mapped company function");
console.log(mappingComp.forEach(company=>console.log(company)));
In the above snippet there is no change in start field of companies array . Why ?
In case I do below I do get modified values for start field from companies array.
var mappingComp=companies.map(company=>company.start+10);
You aren't assigning the result of company.start+10 to anything - it's just an orphaned expression.
var mappingComp = companies.map(company => {
company.start + 10;
return company
});
is just like
var mappingComp = companies.map(company => {
33;
return company
});
The expression is evaluated to a value and then discarded. If you want to add 10 to company.start, use += or =:
var companies=[
{name:'Vicky',category:'Devdas',start:1993,end:2090},
{name:'Vikrant',category:'Devdas',start:1994,end:2019},
{name:'Akriti',category:'mental',start:1991,end:2021},
{name:'Dummy',category:'dummyCategory',start:1995,end:2018},
{name:'Dummy 1',category:'dummyCategory',start:1993,end:2029}
];
var mappingComp = companies.map(company => {
company.start += 10;
return company;
});
console.log(mappingComp);
But this will mutate the original array, which is (often) not a great idea when using map. If you don't want to change the original array, map to a new object:
var companies=[
{name:'Vicky',category:'Devdas',start:1993,end:2090},
{name:'Vikrant',category:'Devdas',start:1994,end:2019},
{name:'Akriti',category:'mental',start:1991,end:2021},
{name:'Dummy',category:'dummyCategory',start:1995,end:2018},
{name:'Dummy 1',category:'dummyCategory',start:1993,end:2029}
];
var mappingComp = companies.map(({ start, ...rest }) => ({
start: start + 10,
...rest
}));
console.log(mappingComp);
company.start + 10 is a simple expression. It's not an assignment statement, that you are expecting it to be. And you are returning the initial array company so it makes sense that it will be returned unaltered.
when you tried the single line fat arrow function with the map. What happens is that you created another entirely different array of mutated values. The array created was populated with values (company.start +10) and returned. Note: This actually didn't change the initial array ie company.
Read up on fat arrow functions, map, filter.

Cannot Read Property 'Push' of undefined - Typescript

When I try to add to an array in Typescript (wrapped in Ionic2) I get an error telling me the array is undefined even though I've declared it. I've tried declaring it using two different declarations and not found the problem. The two declarations I used are:
tracker: any[];
and
tracker: Array<any>;
The first time I try to add anything to the array and where I get the error is below. I wanted to include the whole function, just in case there was something in there that could be redefining what 'this' is:
// Answer Correctly
answerQuestionCorrectly(answer) {
let answerButton = <HTMLButtonElement>document.getElementById('answer-' + answer.AnswerId);
answerButton.addEventListener('click', (event) => {
// Increase the score
this.currentScore = this.currentScore + this.countdown;
// Set up quiz review
var correct = answer.AnswerText;
var qTrack = {no: this.questionNo, q: this.questionText, a: answer.AnswerText, c: correct}
console.log(qTrack);
this.tracker.push(qTrack);
console.log(this.tracker);
// Check for end of questions
if (this.questionNo < this.noOfQuestions) {
// Remove the old answers
var parent = document.getElementById('answers');
this.answers.forEach(element => {
var button = <HTMLButtonElement>document.getElementById('answer-' + element.AnswerId);
parent.removeChild(button);
});
// Re-init the timer
this.timer.initTimer();
// Load Next Question
this.loadQuestion();
} else {
// End the Quiz
this.endOfQuiz();
}
});
}
Those declarations only specify the type of the variable — it also needs a value. Try something like
var tracker: any[] = [];
to initialise the variable to an empty array.
You have to initialize the array before you can push an object into it.
tracker: any[ ] = [ ];
You must initialize it like this:
tracker: Array<any>=[];

Categories

Resources