Далее на странице...
Продолжается практическая работа с кодом JavaScript. Это четвертая по счету практическая задача.
Здесь нужно будет рефакторить код из предыдущей задачи: код будет преобразовываться с использованием объектов.
Рефакторинг - это перепроектирование кода, переработка кода, преобразование алгоритмов — процесс изменения внутренней структуры программы.
1) У нас уже есть рабочее приложение (см. ниже исходный код - из прошлого задания), состоящее из отдельных функций.
Представьте, что перед вами стоит задача переписать его так, чтобы все функции стали методами объекта personalMovieDB. Такое случается в реальных продуктах при смене технологий или подхода к архитектуре программы.
2) Создать метод toggleVisibleMyDB, который при вызове будет проверять свойство privat. Если оно false - он переключает его в true, если true - переключает в false. Протестировать вместе с showMyDB.
3) В методе writeYourGenres запретить пользователю нажать кнопку "Отмена" или оставлять пустую строку. Если он это сделал - возвращать его к этому же вопросу.
После того, как все жанры введены - при помощи метода forEach вывести в консоль сообщения в таком виде: "Любимый жанр #(номер по порядку, начиная с 1) - это (название из массива)"
Код взять из предыдущего домашнего задания.
Исходный код - из прошлого задания
Функции из кода, представленного ниже, должны быть перезаписаны как методы объекта personalMovieDB.
/* Объявляем переменную numberOfFilms глобально, чтобы работать с ней внутри функции */
let numberOfFilms;
// 1. Функция для проверки введенных данных при ответе на 1-ый вопрос
function start(){
numberOfFilms = +prompt('Сколько фильмов вы уже посмотрели?');
/* Проверка: на пустое поле для ввода ИЛИ на кнопку Отмена ИЛИ
на НЕ число, то снова задаем вопрос... */
while(numberOfFilms == '' || numberOfFilms == null || isNaN(numberOfFilms)){
numberOfFilms = +prompt('Сколько фильмов вы уже посмотрели?');
}
}
start(); // Вызов функции
// --------- Главный объект программы ---------
const personalMovieDB = {
count: numberOfFilms,
movies: {},
actors: {},
genres: [],
private: false
};
// 2. Функция заносит в главный объект программы информацию о фильмах
function rememberMyFilms(){
for (let i = 0; i < 2; i++) {
const a = prompt(`Один из последних просмотренных фильмов ${i + 1}`),
b = prompt('На сколько оцените его?');
/* Проверка на пустое поле для ввода ИЛИ на кнопку Отмена ИЛИ на количество символов */
if(a != '' && b != '' && a != null && b != null && a.length < 50) {
personalMovieDB.movies[a] = b;
console.log('done');
}
else{
console.log('error');
i--;
}
}
}
rememberMyFilms(); // Вызов функции
// 3. Функция анализа уровня Киномании
function detectPersonalLevel(){
if (personalMovieDB.count < 10) {
console.log('Просмотрено довольно мало фильмов');
} else if (personalMovieDB.count > 10 && personalMovieDB.count < 30) {
console.log('Вы классический зритель');
} else if (personalMovieDB.count > 30) {
console.log('Вы киноман');
} else {
console.log('Произошла ошибка');
}
}
detectPersonalLevel(); // Вызов функции
// 4. Функция Жанров - 3-я часть задания
function writeYourGenres(){
for(let i = 1; i <= 3; i++){
personalMovieDB.genres[i - 1] = prompt(`Ваш любимый жанр номер ${i}`);
}
}
writeYourGenres(); // Вызов функции
// 5. Функция проверки приватности БД - 2-я часть задания
function showMyDB(hidden){
if(!hidden){
console.log(personalMovieDB); // Выводим главный объект программы
}
}
showMyDB(personalMovieDB.private); // Вызов функции
Результат
Далее (см. код ниже) следует рефакторинг исходного кода и выполнение 2-ой и 3-ей части задания:
1. Первая часть задания. Из всех функций (из исходного кода) редактируется только метод start() следующим образом: переменная numberOfFilms уже не используется, так как ответ на 1-ый вопрос сразу заносится в свойство count объекта personalMovieDB.
2. Решение 2-ой части задания. Создается метод toggleVisibleMyDB, который переключает приватность/видимость БД. Метод toggleVisibleMyDB меняет значение свойства privat на противоположное: true <--> false.
3. Дополняется метод Жанров writeYourGenres в соответствии с условием - 3-я часть задания.
При этом используется стрелочная функция.
Запись (item, i) => {...} аналогична записи function(item, i) {...}
Рефакторинг кода + 2-я и 3-я часть задания
// 1-я часть задания - Перезапись функций, как методов объекта personalMovieDB
const personalMovieDB = {
count: 0,
movies: {},
actors: {},
genres: [],
private: false,
// Метод start - Начало: первый вопрос...
start: function() {
personalMovieDB.count = +prompt('Сколько фильмов вы уже посмотрели?');
// Проверка: на пустое поле для ввода ИЛИ на кнопку Отмена ИЛИ на НЕ число
while (personalMovieDB.count == '' || personalMovieDB.count == null || isNaN(personalMovieDB.count)) {
personalMovieDB.count = +prompt('Сколько фильмов вы уже посмотрели?');
}
},
// Метод rememberMyFilms - Информация о фильмах
rememberMyFilms: function() {
for (let i = 0; i < 2; i++) {
const a = prompt(`Один из последних просмотренных фильмов №_${i+1}`),
b = prompt('На сколько оцените его?');
/* Проверка на пустое поле для ввода ИЛИ на кнопку Отмена ИЛИ на количество символов */
if (a != '' && b != '' && a != null && b != null && a.length < 50) {
personalMovieDB.movies[a] = b;
console.log('done');
}
else {
console.log('error');
i--;
}
}
},
// Метод detectPersonalLevel - Анализ уровня Киномании
detectPersonalLevel: function() {
if (personalMovieDB.count < 10) {
console.log('Просмотрено довольно мало фильмов');
} else if (personalMovieDB.count > 10 && personalMovieDB.count < 30) {
console.log('Вы классический зритель');
} else if (personalMovieDB.count > 30) {
console.log('Вы киноман');
} else {
console.log('Произошла ошибка');
}
},
// Метод showMyDB - проверка приватности БД и вывод главного Объекта программы
// Аргумент hidden - Свойство private: false или true
showMyDB: function(hidden) {
if(!hidden){
console.log(personalMovieDB);
}
},
// 2-я часть задания - метод toggleVisibleMyDB
// Переключаем приватность/видимость БД
toggleVisibleMyDB: function() {
if(personalMovieDB.private){
personalMovieDB.private = false;
}
else {
personalMovieDB.private = true;
}
},
// 3-я часть задания - метод Жанров writeYourGenres
writeYourGenres: function() {
for (let i = 1; i <= 3; i++) {
let genre = prompt(`Ваш любимый жанр номер ${i}`);
// Проверка на пустое поле для ввода ИЛИ на кнопку Отмена
if(genre == '' || genre == null){
console.log('Вы ввели некорректные данные или не ввели их вовсе');
i--;
}
else{
personalMovieDB.genres[i - 1] = genre;
}
}
// Вывод любимых жанров №... - Метод forEach
personalMovieDB.genres.forEach((item, i) => {
console.log(`Любимый жанр ${i + 1} - это ${item}`);
});
}
};
Результат
Пример тестирования кода в консоли Браузера
// 1. Тестирование - метода Жанров - 3-я часть задания....
personalMovieDB.writeYourGenres();
2 Вы ввели некорректные данные или не ввели их вовсе
Любимый жанр 1 - это qwe
Любимый жанр 2 - это qwerty
Любимый жанр 3 - это asdf
// ...в результате в массиве жанров - 3 Элемента
personalMovieDB
{count: 0, movies: {…}, actors: {…}, genres: Array(3), private: false, …}
// 2. Тестирование метода showMyDB
// Т. к. значение свойства private: false - Метод выводит главный Объект программы
personalMovieDB.showMyDB(personalMovieDB.private)
{count: 0, movies: {…}, actors: {…}, genres: Array(3), private: false, …}
undefined
// 3. Тестирование метода toggleVisibleMyDB....
personalMovieDB.toggleVisibleMyDB();
undefined
// ...после этого меняется значение свойства private: true
personalMovieDB
{count: 0, movies: {…}, actors: {…}, genres: Array(3), private: true, …}
// Поэтому метод showMyDB - УЖЕ НЕ выводит главный Объект программы
personalMovieDB.showMyDB(personalMovieDB.private);
undefined
// ........ Дополнительно тестируем методы start() и detectPersonalLevel()
personalMovieDB.start();
undefined
personalMovieDB
{count: 21, movies: {…}, actors: {…}, genres: Array(3), private: true, …}
personalMovieDB.detectPersonalLevel();
Вы классический зритель
undefined
Тестирование кода в консоли Браузера заключается в том, что в консоли вызываются те методы главного объекта программы personalMovieDB, которые мы хотим проверить.
При этом, если в методе объекта personalMovieDB используется метод prompt, то в окне браузера появляется окно для ввода данных.
Почему при работе в консоли с методами объекта мы видим undefined? Потому что эти методы объекта ничего не возвращают, а просто работают с данными. Это особенность консоли, которая ни на что не влияет.
Оптимизация кода для 3-ей части задания
Оптимизация кода для 3-ей части задания заключается в следующем: нужно сделать так, чтобы пользователь ввел сразу все жанры в виде одной строки, из которой формируется массив. Элементы массива сортируются в алфавитном порядке.
// 3-я часть задания - метод Жанров writeYourGenres
writeYourGenres: function() {
for (let i = 1; i < 2; i++) {
let genre = prompt(`Введите ваши любимые жанры через пробел`).toLowerCase();
// Метод toLowerCase() переводит строку в нижний регистр
if(genre == '' || genre == null){
console.log('Вы ввели некорректные данные или не ввели их вовсе');
i--;
}
else{
personalMovieDB.genres = genre.split(' '); // Формируем массив из строки
personalMovieDB.genres.sort(); // Сортировка массива
}
}
// Вывод любимых жанров №... - Метод forEach
personalMovieDB.genres.forEach((item, i) => {
console.log(`Любимый жанр ${i + 1} - это ${item}`);
});
}
Результат
Пример тестирования кода в консоли Браузера
personalMovieDB.writeYourGenres();
Любимый жанр 1 - это боевик
Любимый жанр 2 - это вестерн
Любимый жанр 3 - это комедия
Любимый жанр 4 - это ужасы
undefined
1. Вопрос о жанрах задается один раз, но здесь все равно используется цикл. Сделано это для того, чтобы вернуть пользователя к вопросу, если он оставил пустым поле для ввода или нажал "Отмена".
2. Метод toLowerCase() - переводит строку в нижний регистр, чтобы метод sort() сортировал элементы массива без учета регистра.
3. Метод split - формирует массив из строки по указанному разделителю - это пробел.