Я прохожу курс кодирования в Codecademy и в настоящее время застрял в определенном вопросе в рамках задачи по кодированию. Я получил 3 JS-файла, два из которых мне не следует каким-либо образом изменять, так как мне сказали, что это вспомогательные функции, которые мне следует использовать, и файл с массивом книг. Вопрос 2 полностью сбивает меня с толку. Я сидел над ним уже целых 2 часа, и хотя он работает локально на vscode, он снова и снова выдает мне одно и то же сообщение об ошибке. Буду очень признателен за любую помощь, потому что я очень расстроен. Сначала я пришлю описание задачи и первый вопрос для дополнительного контента:
Вступление: В редакторе кода мы предоставили вам стартовый код веб-сайта Book Finder. Как только заявка будет заполнена, вы сможете ввести жанр, название или автора в строку поиска и получить список книг, соответствующих этим критериям. Вы можете увидеть список книг, которые ваше приложение будет искать в bookList.js.
Ваша задача — завершить сборку приложения, заполнив определения функций captureSearchValue(), filterBooks(), StructureBooksAsHtml() и searchBtnClickHandler(). Вам следует вносить изменения только в эти четыре определения функций в script.js. В helper.js мы определили вспомогательные функции, которые вам нужно будет использовать при создании программы.
Вопрос 1: Функция captureSearchValue фиксирует входное значение панели поиска и возвращает его.
По их мнению, мой код для первого вопроса правильный.
Вопрос 2: Функция filterBooks() принимает строку поиска и список книг в качестве параметров и возвращает все книги, которые содержат точное соответствие входным данным поиска, в виде массива объектов. Объекты в этом массиве должны быть отформатированы как книги со свойствами названия, автора и тегов, аналогично исходному массиву книг. Он должен использовать функцию FlattenObjectValuesIntoArray() для легкого поиска по всем полям внутри объекта книги.
Вспомогательный код:
// Flatten object keys into an array so that we search the entire object by the input value
const flattenObjectValuesIntoArray = (arrOfObjs) => {
let flattenedObj;
const flattenedObjsArr = [];
for (let obj = 0; obj < arrOfObjs.length; obj++) {
const objValues = Object.values(arrOfObjs[obj]);
flattenedObj = [...objValues.flat()]
flattenedObjsArr.push(flattenedObj)
}
return flattenedObjsArr;
};
// Structure filtered books as HTML and return
const structureBookAsHtml = (book) => {
const bookDiv = document.createElement("div");
bookDiv.setAttribute('class', 'bookDiv');
const bookTitle = document.createElement("h2");
bookTitle.innerHTML = book.title;
bookTitle.setAttribute('class', 'bookTitle');
const bookAuthor = document.createElement("h3");
bookAuthor.innerHTML = book.author;
const bookTags = document.createElement("p");
bookTags.innerHTML = book.tags.join(", ");
bookDiv.append(bookTitle, bookAuthor, bookTags);
return bookDiv;
};
const renderBooksToDom = (elements) => {
const bookListContainer = document.querySelector("#bookList");
bookListContainer.innerHTML = "";
bookListContainer.append(...elements);
};
Файл массива:
const books = [
{
title: "The City We Became",
author: "N. K. Jemisin",
tags: ["fantasy", "fiction", "afrofutursim", "science fiction", "sci-fi"]
},
{
title: "The Catcher in the Rye",
author: "J. D. Salinger",
tags: ["fiction", "young adult", "YA", "realism", "coming of age", "classic"]
},
{
title: "The Hundred Thousand Kingdoms",
author: "N. K. Jemisin",
tags: ["fantasy", "fiction", "adventure", "series"]
},
{
title: "Sapiens: A Brief History of Humankind",
author: "Yuval Noah Harari",
tags: ["nonfiction", "history", "anthropology", "science", "sociology"]
},
{
title: "Behave: The Biology of Humans at Our Best and Worst",
author: "Robert M. Sapolsky",
tags: ["nonfiction", "anthropology", "science", "sociology", "biology"]
},
{
title: "The Parable of the Talents",
author: "Octavia Butler",
tags: ["fiction", "dystopian", "science fiction"]
},
{
title: "1984",
author: "George Orwell",
tags: ["fiction", "dystopian", "science fiction", "classics", "adult"]
},
{
title: "Remarkably Bright Creatures",
author: "Shelby Van Pelt",
tags: ["fiction", "mystery", "magical realism"]
},
{
title: "Crying in H Mart",
author: "Michelle Zauner",
tags: ["memoir", "nonfiction", "autobiography"]
},
{
title: "Wild: From Lost to Found on the Pacific Crest Trail",
author: "Cheryl Strayed",
tags: ["nonfiction", "memoir", "adventure", "travel"]
}
]
Индекс.html:
<!DOCTYPE html>
<html>
<head>
<link rel = "stylesheet" href = "styles.css">
<script src = "bookList.js"></script>
<script src = "bookList.test.js"></script>
<script src = "helper.js"></script>
<script src = "script.js" defer></script>
</head>
<body>
<h1>Book Finder</h1>
<input id = "search-bar" type = "text" placeholder = "Search for books by tags">
<button class = "btn" id = "search-btn">Search</button>
<div id = "bookList">
<!-- List of books will be rendered here -->
</div>
</body>
</html>
мой код:
// Click handler for search button
let cap = document.getElementById('search-bar')
let capValue = cap.value;
const captureSearchValue = () => {
return cap.value
};
const filterBooks = () => {
let flattenedArr =flattenObjectValuesIntoArray(books);
let match = [];
for (let i = 0; i < flattenedArr.length; i++) {
for (let j = 0; j < flattenedArr[i].length; j++) {
if (flattenedArr[i][j] === capValue){
match.push(books[i])
}
}
}; return match
};
// Empty the book list container, iterate over list of filtered books, return list of books formatted as HTML using the function in `helper.js`
const structureBooksAsHtml = () => {};
// Handler triggered when a user clickers the "Search" button. Chains previously defined functions together to filter books based on the search value, formats the books as HTML and renders them to the DOM
const searchBtnClickHandler = () => {};
// Grab search button from the DOM
// Attach an event listener to the search button
searchBtn.addEventListener("click", () => {
searchBtnClickHandler(books);
});
Я занимаюсь только функцией filterBooks, до других функций я еще не добрался, так что не обращайте на них внимания.
Это сообщение, которое я получаю на вопрос 2, когда отправляю свой ответ:
Учитывая фильтр fantasy, ваша функция filterBooks вернула массив с элементами 0. Мы ожидали его возвращения 2.
Буду очень признателен за любую помощь по этой проблеме. Мне кажется, это не имеет никакого смысла
Я думаю, что проблема связана с капитализацией, но я, честно говоря, понятия не имею.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы создали переменную вне функции, которая задается при загрузке DOM один раз, поэтому при загрузке DOM входное значение search-bar равно ''. Вот почему при выполнении цикла вы каждый раз проверяете, равна ли строка book значению ''. Это вызывает проблему.
Есть простое решение этой проблемы: просто используйте функцию captureSearchValue, чтобы создать переменную capValue внутри функции fiterBooks, и тогда она будет работать нормально.
Вот как должен выглядеть ваш код
const searchBtn = document.querySelector('#search-btn');
// Click handler for search button
let cap = document.getElementById('search-bar')
// Remove the capValue variable
const captureSearchValue = () => {
return cap.value
};
const filterBooks = () => {
let flattenedArr = flattenObjectValuesIntoArray(books);
// Add the capValue variable here
let capValue = captureSearchValue();
let match = [];
for (let i = 0; i < flattenedArr.length; i++) {
for (let j = 0; j < flattenedArr[i].length; j++) {
if (flattenedArr[i][j] === capValue) {
match.push(books[i])
}
}
};
return match
};
Если это не сработает, вы также можете попробовать изменить условие на:
if (flattenedArr[i][j].includes(capValue)) {
match.push(books[i])
}
Предыдущее условие проверяло, соответствует ли значение строки книги на 100% значению поиска, что также может вызывать проблему, например 'fantasy' !== ' fantasy ' даже пробел может привести к тому, что это значение будет ложным. Новое условие просто проверяет, включена ли строка или нет. Это также может решить проблему.
Привет! Я очень ценю помощь, но, к сожалению, после того, как я ее попробовал, я получил одно и то же сообщение: учитывая фильтр fantasy, ваша функция filterBooks вернула массив с элементами 0. Мы ожидали его возвращения 2. Я в таком замешательстве, что не вижу никакой причины, по которой это может быть неправильно...
Я скопировал весь ваш код, просмотрел его, исправил проблему и обновил свой ответ. Проверьте еще раз, надеюсь, это решит проблему.
Вам действительно следует научиться:
Вы можете заменить все эти функции на forEach, но их изучение значительно улучшит ваш код :)
Это может быть результат:
///////////////////
// DATA
//////////////////
const books = [
{
title: "The City We Became",
author: "N. K. Jemisin",
tags: ["fantasy", "fiction", "afrofutursim", "science fiction", "sci-fi"]
},
{
title: "The Catcher in the Rye",
author: "J. D. Salinger",
tags: ["fiction", "young adult", "YA", "realism", "coming of age", "classic"]
},
{
title: "The Hundred Thousand Kingdoms",
author: "N. K. Jemisin",
tags: ["fantasy", "fiction", "adventure", "series"]
},
{
title: "Sapiens: A Brief History of Humankind",
author: "Yuval Noah Harari",
tags: ["nonfiction", "history", "anthropology", "science", "sociology"]
},
{
title: "Behave: The Biology of Humans at Our Best and Worst",
author: "Robert M. Sapolsky",
tags: ["nonfiction", "anthropology", "science", "sociology", "biology"]
},
{
title: "The Parable of the Talents",
author: "Octavia Butler",
tags: ["fiction", "dystopian", "science fiction"]
},
{
title: "1984",
author: "George Orwell",
tags: ["fiction", "dystopian", "science fiction", "classics", "adult"]
},
{
title: "Remarkably Bright Creatures",
author: "Shelby Van Pelt",
tags: ["fiction", "mystery", "magical realism"]
},
{
title: "Crying in H Mart",
author: "Michelle Zauner",
tags: ["memoir", "nonfiction", "autobiography"]
},
{
title: "Wild: From Lost to Found on the Pacific Crest Trail",
author: "Cheryl Strayed",
tags: ["nonfiction", "memoir", "adventure", "travel"]
}
]
///////////////////
// HELPERS
//////////////////
function flattenObjectValuesIntoArray (arrOfObjs) {
let flattenedObj;
const flattenedObjsArr = [];
for (let obj = 0; obj < arrOfObjs.length; obj++) {
const objValues = Object.values(arrOfObjs[obj]);
flattenedObj = [...objValues.flat()]
flattenedObjsArr.push(flattenedObj)
}
return flattenedObjsArr;
};
///////////////////
// TASK
//////////////////
/*
The filterBooks() function takes in a search string and a list of books as parameters and returns all of the books that contain an exact match of the search input as an array of objects.
*/
function filterBooks(search, books) {
// Flatten books array
flattenedBooks = flattenObjectValuesIntoArray(books);
// Now we can filter for an EXACT match
let results = flattenedBooks.filter(bookProps =>
bookProps.filter((prop) => prop === search).length
)
// We still got to remap like the books array, but if we assume titles are unique, we can still use the original books array to find the correct objects.
let mappedResults = results.map(book => books.find((b) => b.title === book[0]))
return mappedResults
}
// EXAMPLE
console.info(filterBooks('fiction', books));И последнее, но не менее важное: о
'fantasy' !== ' fantasy '
Это легко исправить с помощью функции Trim() :)
«Функция filterBooks() принимает в качестве параметров строку поиска и список книг». Ваша функция
filerBooksдолжна иметь два параметра, в настоящее время у нее их нет. Итак,capValueиbooksдолжны быть параметрами. Вам не нужно создаватьcapaValueв глобальной области (т. е. вышеcaptureSearchValue).