Object Constructors - javascript

I have a problem with creating a new Object in the constructor
My Aim is to take the user input and from that create a new object and push into an array using the constructor.
The problem is that when I try to fill the new input to create a new object it just replaced the old one with undefined values.
MY code :
let Book = document.querySelector("#one");
let Author = document.querySelector("#two");
let Year = document.querySelector("#three");
let Btn = document.querySelector("button");
Btn.addEventListener("click", () => {
Book = Book.value;
Author = Author.value;
Year = Year.value;
let myLibrary = [];
function newBook(name, author, year) {
this.name = name;
this.author = author;
this.year = year;
}
function addBookToLibrary(book, author, year) {
const Books = new newBook(book, author, year);
myLibrary.push(Books);
}
addBookToLibrary(Book, Author, Year);
console.log(myLibrary);
});

let Book = document.querySelector("#one");
let Author = document.querySelector("#two");
let Year = document.querySelector("#three");
let Btn = document.querySelector("button");
let myLibrary = [];
Btn.addEventListener("click", () => {
function newBook(name, author, year) {
this.name = name;
this.author = author;
this.year = year;
}
function addBookToLibrary(book, author, year) {
const Books = new newBook(book, author, year);
myLibrary.push(Books);
}
addBookToLibrary(Book.value, Author.value, Year.value);
console.log(myLibrary);
});
There are two mistakes in above code:
You are using local state of let myLibrary = []; which will be created on every click. It should be moved to a higher level so that on every click the value added can be preserved.
You are using same name of variables inside your function, which are overriding the Dom reference.

Related

Cannot read properties of undefined (Inside a Constructor)

I'm building a library app from The Odin Project, and this error occurs when I try to change read status for Not Read read using a click event.
the error occurs on line 88, reading status value. How can I fix that?
thank you.
console.log(
"What is the toggle initial value?...",
myLibrary[parseInt(retrieveBookToToggle)].status
);
let myLibrary = [];
const btnAdd = document.querySelector("btn-add");
//Object Constructor
class Book {
constructor(title, author, pages, status) {
this.title = title;
this.author = author;
this.pages = pages;
this.status = status;
}
//Add a new book to array
function addBookToLibrary(title, author, pages, status) {
let book = new Book(title, author, pages, status);
myLibrary.push(book);
displayBooksOnPage()
}
//Display array to card
function displayBooksOnPage() {
const books = document.querySelector(".books-container");
//remove displayed cards before loop array
const removeDivs = document.querySelectorAll(".card");
console.log("Show me the node count of the current card divs........", removeDivs);
for (let i = 0; i < removeDivs.length; i++) {
removeDivs[i].remove();
}
//Loop Library array and display to the cards
let index = 0;
myLibrary.forEach(myLibrarys => {
const card = document.createElement("div");
card.classList.add("card");
books.appendChild(card);
//remove book button
const removeBookButton = document.createElement("button");
removeBookButton.classList.add("remove-book-button");
removeBookButton.textContent = "Remove Book";
console.log("show me my currentnarray objects inside of foreach........", myLibrary);
//link data attribute of the remove button to the array and card
removeBookButton.dataset.linkedArray = index;
index++;
console.log("show me dataset link back to the array...", removeBookButton.dataset.linkedArray);
card.appendChild(removeBookButton);
//start event listener/remove array item from array and card from parent div via data link
removeBookButton.addEventListener("click", removeBookFromLibrary);
function removeBookFromLibrary() {
let retrieveBookToRemove = removeBookButton.dataset.linkedArray;
console.log("attempting to remove array item via data attribute...", parseInt(retrieveBookToRemove));
myLibrary.splice(parseInt(retrieveBookToRemove), 1);
card.remove();
displayBooksOnPage;
}
const readStatusButton = document.createElement("button");
readStatusButton.classList.add("read-status-button");
readStatusButton.textContent = "Change Status";
readStatusButton.dataset.linkedArray = index;
console.log("show dataset link back to the array for read status button", readStatusButton.dataset.linkedArray);
card.appendChild(readStatusButton);
readStatusButton.addEventListener("click", toggleReadStatus);
function toggleReadStatus() {
let retrieveBookToToggle = readStatusButton.dataset.linkedArray;
Book.prototype = Object.create(Book.prototype);
const toggleBook = new Book();
console.log("what's the toggle initial value? ", myLibrary[parseInt(retrieveBookToToggle)].status);
if (myLibrary[parseInt(retrieveBookToToggle)].status == "Read") {
toggleBook.status = "Not Read";
myLibrary[parseInt(retrieveBookToToggle)].status = toggleBook.status;
} else if (myLibrary[parseInt(retrieveBookToToggle)].status == "Not Read") {
toggleBook.status = "Read";
myLibrary[parseInt(retrieveBookToToggle)].status = toggleBook.status;
}
displayBooksOnPage();
}
for (let key in myLibrarys) {
const para = document.createElement("p");
para.textContent = (`${myLibrarys[key]}`);
card.appendChild(para);
}
})
}
const addBookButton = document.querySelector(".btn-add");
addBookButton.addEventListener("click", displayTheForm);
function displayTheForm() {
document.getElementById("books-form").style.display = "";
}
const submitButton = document.querySelector(".btn-add");
submitButton.addEventListener("click", intakeFormData);
function intakeFormData() {
let Title = document.getElementById("title").value;
let Author = document.getElementById("author").value;
let Pages = document.getElementById("pages").value;
let Status = document.getElementById("status").value;
if ((Title == "") || (Author == "") || (Pages == "") || (Status == "")) {
return;
}
addBookToLibrary(Title, Author, Pages, Status);
document.getElementById("add-book").reset();
}
const clearButton = document.getElementById("btn-reset");
clearButton.addEventListener("click", clearForm());
function clearForm() {
document.getElementById("add-book").reset();
}

How do I add increment to two specific properties of a class?

Here are my instructions, I am having issues with getting two properties 'numberOfLikes' and 'comments' to use increment to adjust the amount of likes and comments. I don't know if I should use a for loop or if I just need the increment operator. I'm new to coding and apologize in advance.
/*
In the space below, add to the existing skeleton of a Tweet class.
A tweet should have a (dynamic) author, content, timeStamp, numberOfLikes, and comments.
A tweet should be able to increment the numberOfLikes and add to the list of comments.
Create several instances of your Tweet and log them to the console. Make sure the
tweet object instances behave as expected.
*/
class Tweet {
constructor(author, content, timeStamp, numberOfLikes, comments) {
this.author = author;
this.content = content;
this.timeStamp = timeStamp;
this.numberOfLikes = numberOfLikes;
this.comments = comments;
}
};
//This is code I was playing around with, doesn't work
this.add = function(numberOfLikes){
for(i = 0; i < numberOfLikes.length; i++){
console.log("You have " + numberOfLikes + " likes");
}
}
this.add = function(comments) {
for(i = 0; i < comments.length; i++) {
console.log("You have " + comments + " comments");
}
}
var tweet1 = new Tweet("Rihanna", "Fenty Beauty", "12:31 A.M.", 120193, 6782);
Thanks in advance!
A tweet should be able to increment the numberOfLikes
This should be a function to increase the numberOfLikes.
and add to the list of comments.
comments is probably an array. This means that you need a function to add a comment, to the list of your comments.
class Tweet {
constructor(author, content, timeStamp, numberOfLikes, comments) {
this.author = author;
this.content = content;
this.timeStamp = timeStamp;
this.numberOfLikes = numberOfLikes;
this.comments = comments;
}
increaseNumberOfLikes() {
this.numberOfLikes++
}
addComment(commentText) {
this.comments.push(commentText)
}
};
let tweet1 = new Tweet("The Weekend", "Some content", "15:31 P.M.", 9800, ["so cool", "do it again"])
tweet1.increaseNumberOfLikes()
tweet1.addComment("Great Song!")
console.log(tweet1)
You should create more tweets like above.
You can create functions that use += and array#push to increment numbers and add values to arrays.
Incrementing tweets:
incrementLikes(increment = 1) {
this.numberOfLikes += increment
}
Adding a comment to the array:
addComment(comment) {
this.comments.push(comment)
}
I also noticed that in your post you mentioned that this.comments was a list. So I made that change when initializing the class.
new Tweet("Rihanna", "Fenty Beauty", "12:31 A.M.", 120193, ["amazing", "wow"]);
Demo:
class Tweet {
constructor(author, content, timeStamp, numberOfLikes, comments) {
this.author = author;
this.content = content;
this.timeStamp = timeStamp;
this.numberOfLikes = numberOfLikes;
this.comments = comments;
}
incrementLikes(increment = 1) {
this.numberOfLikes += increment
}
addComment(comment) {
this.comments.push(comment)
}
};
var tweet1 = new Tweet("Rihanna", "Fenty Beauty", "12:31 A.M.", 120193, ["amazing", "wow"]);
tweet1.incrementLikes()
console.log(tweet1.numberOfLikes)
tweet1.incrementLikes()
console.log(tweet1.numberOfLikes)
tweet1.addComment("This is a comment")
console.log(tweet1.comments)
Within the class body you need to define prototypal functions like this:
class Tweet {
constructor(author, content, timeStamp, numberOfLikes, comments) {
this.author = author;
this.content = content;
this.timeStamp = timeStamp;
this.numberOfLikes = numberOfLikes;
this.comments = comments;
}
like() {
this.numberOfLikes++;
}
comment(comment) {
this.comments.push(comment);
}
}
const tweet1 = new Tweet("Rihanna", "Fenty Beauty", "12:31 A.M.", 120193, ["I hate I hate know-it-alls"]);
console.log(tweet1.numberOfLikes);
tweet1.like();
tweet1.like();
console.log(tweet1.numberOfLikes);
console.log(tweet1.comments);
tweet1.comment("I love you Rihanna!!")
console.log(tweet1.comments);
.as-console-wrapper { min-height: 100%!important; top: 0; }
This should work. You need to put the function definitions inside the class definition. I also modified the function names, because they conflict with each other.
class Tweet {
constructor(author, content, timeStamp, numberOfLikes, comments) {
this.author = author;
this.content = content;
this.timeStamp = timeStamp;
this.numberOfLikes = numberOfLikes;
this.comments = comments;
}
addLikes(numberOfLikes){
this.numberOfLikes += numberOfLikes
}
addComments(comments) {
this.comments += comments
}
};
// Initial tweet instance
var tweet1 = new Tweet("Rihanna", "Fenty Beauty", "12:31 A.M.", 120193, 6782);
// Call modifiers
tweet1.addLikes(5)
tweet1.addComments(7)
// Check the variables were modified
console.log(tweet1.numberOfLikes)
console.log(tweet1.comments)

Pushing a constructor to an array

I'm having a hard time solving this.
For my project I would like to use constructor to store informations via prompts into an array, but I'm not making it.
This is the code:
const employeeList = [];
let btnprocess = document.getElementById("initbtn");
btnprocess.addEventListener("click", employeeOk);
function employeeOk() {
const name = prompt("What's your name?:");
const position = prompt("Which is your position?:");
const salary = +prompt("Your Salary?");
class Employee {
constructor(name, position, salary) {
this.name = name;
this.position = position;
this.salary = salary;
}
employeeReady(){
const employee1 = new Employee(name, position, salary);
employeeList.push(employee1);
}
}
}
try this solution to achieve above problem
class Employee {
constructor(name, position, salary) {
this.name = name;
this.position = position;
this.salary = salary;
}
}
const employeeList = [];
function employeeOk() {
const name = prompt("What's your name?:");
const position = prompt("Which is your position?:");
const salary = +prompt("Your Salary?");
const employee1 = new Employee(name, position, salary);
employeeList.push(employee1);
}
let btnprocess = document.getElementById("initbtn");
btnprocess.addEventListener("click", employeeOk);

Class object overlapping

im still trying to learn and im trying to make a group of actors be added to a movie class, i made it work but i still have problems because if you add another actor the last one dissappears, i tried with a loop but i could do nothing.
class Movie {
constructor(title,year,duration){
this.title = title;
this.year = year;
this.duration = duration;
}
addCast(actors){
this.actors = actors
}
}
class Actor {
constructor(name,age)
{
this.name = name;
this.age = age;
}
}
const terminator = new Movie('Terminator I', 1985, 60);
const arnold = new Actor('Arnold Schwarzenegger', 50);
const otherCast = [
new Actor('Paul Winfield', 50),
new Actor('Michael Biehn', 50),
new Actor('Linda Hamilton', 50)
];
//From here it can not be modified
let movieOne = new Movie("Kong","2018","2h30m");
let movieTwo = new Movie("Joker","2019","2h03m");
let movieThree = new Movie("John Wick 3", "2019", "1h49m");
terminator.addCast(arnold);
terminator.addCast(otherCast);
//To here it can not be modified
console.log({movieOne,movieTwo,movieThree,terminator});
See? Arnold should be in the actors too but it isnt! Thanks for the help in advance.
Another thing, this is for an excercise and i can not modify the lines i commented.
You have
addCast(actors){
this.actors = actors
}
This does not add the passed actor array to the actors on the instance - it replaces the instance's actors with the passed argument. Calling addCast will result in whatever previously existed on actors being lost.
To help reduce bugs, it can help to name methods appropriately - for logic like this, I'd call it setCast, not addCast.
If you want to add onto the end of the existing cast, and you're not sure whether the argument will be a single actor to add or an array of actors to add, use:
addCast(actorOrActors) {
if (Array.isArray(actorOrActors)) {
this.actors.push(...actorOrActors);
} else {
this.actors.push(actorOrActors);
}
}
class Movie {
constructor(title, year, duration) {
this.title = title;
this.year = year;
this.duration = duration;
this.actors = [];
}
addCast(actorOrActors) {
if (Array.isArray(actorOrActors)) {
this.actors.push(...actorOrActors);
} else {
this.actors.push(actorOrActors);
}
}
}
class Actor {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
const terminator = new Movie('Terminator I', 1985, 60);
const arnold = new Actor('Arnold Schwarzenegger', 50);
const otherCast = [
new Actor('Paul Winfield', 50),
new Actor('Michael Biehn', 50),
new Actor('Linda Hamilton', 50)
];
//From here it can not be modified
let movieOne = new Movie("Kong", "2018", "2h30m");
let movieTwo = new Movie("Joker", "2019", "2h03m");
let movieThree = new Movie("John Wick 3", "2019", "1h49m");
terminator.addCast(arnold);
terminator.addCast(otherCast);
//To here it can not be modified
console.log({
movieOne,
movieTwo,
movieThree,
terminator
});
This is because in your addCast() method, each time you call it, you are replacing the previous value instead of appending it
You overwrite arnold with your second addActors call.
Only add one actor at a time to an array of actors.
class Movie {
constructor(title,year,duration){
this.title = title;
this.year = year;
this.duration = duration;
this.actors = [];
}
addCast(actor){
this.actors.push(actor);
}
terminator.addCast(arnold);
terminator.addCast(otherCast[0]);
terminator.addCast(otherCast[1]);
terminator.addCast(otherCast[2]);

Javascript: Modify an object from a pointer

I'm making a digital library with three classes: Library, Shelf & Book. Shelves have their contents as an array of books. Books have two methods, enshelf and unshelf. When a book gets unshelfed it's supposed to set delete the instance of itself from the shelf it's on and then set it's location property to null. How can I modify the shelf it's sitting on? In the constructor if I change this.location, it will just give that property a new value instead of modifying the variable it points to. I feel like this is really simple and I'm overlooking something super basic.
var _ = require('lodash');
//books
var oldMan = new Book("Old Man and the Sea", "Ernest Hemingway", 0684801221);
var grapes = new Book("The Grapes of Wrath", "John Steinbeck", 0241952476);
var diamondAge = new Book("The Diamond Age", "Neal Stephenson", 0324249248);
//shelves
var shelf0 = new Shelf(0);
var shelf1 = new Shelf(1);
//libraries
var myLibrary = new Library([shelf0, shelf1], "123 Fake Street");
//these need to accept an unlimited amount of each
function Library(shelves, address) {
this.shelves = shelves; //shelves is an array
this.address = address;
this.getAllBooks = function() {
console.log("Here are all the books in the library: ");
for (var i = 0; i < this.shelves.length; i++) {
console.log("Shelf number " + i + ": ");
for (var j = 0; j < this.shelves[i].contents.length; j++) {
console.log(this.shelves[i].contents[j].name);
}
}
}
}
function Shelf(id) {
this.id = id;
this.contents = [];
}
function Book(name, author, isbn) {
this.name = name;
this.author = author;
this.isbn = isbn;
this.location = null;
this.enshelf = function(newLocation) {
this.location = newLocation;
newLocation.contents.push(this);
}
this.unshelf = function() {
_.without(this.location, this.name); //this doesn't work
this.location = null;
}
}
console.log("Welcome to Digital Library 0.1!");
oldMan.enshelf(shelf1);
myLibrary.getAllBooks();
oldMan.unshelf();
myLibrary.getAllBooks();
Small issue with your unshelf method, easily remedied:
this.unshelf = function() {
this.location.contents =
_.without(this.location.contents, this);
this.location = null;
}
Consider, however, that shelf and unshelf should be methods of Shelf, and not of Book. Also, if you must have this method, surround it with a guard, like so:
this.unshelf = function() {
if (this.location) {
this.location.contents =
_.without(this.location.contents, this);
this.location = null;
}
}
Couple of small issues:
without works on arrays and returns a copy of the array with the elements removed - the original is untouched. So you need to pass location.contents instead of just location and reassign it back to location.contents.
Also you add the whole book to the Shelf, then try to remove it by name, so it doesn't match and get removed. So just pass this to without:
this.unshelf = function() {
if (this.location) {
this.location.contents = _.without(this.location.contents, this);
this.location = null;
}
}

Categories