Files

140 lines
7.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: 587d7b8e367417b2b2512b5d
title: Ризики використання Imperative Code
challengeType: 1
forumTopicId: 301241
dashedName: understand-the-hazards-of-using-imperative-code
---
# --description--
Функціональне програмування - хороша звичка. Це дозволяє вам легко керувати своїм кодом та рятує від підступних помилок. Але перед тим, як перейти до цього, варто розібрати імперативний метод програмування, щоб підкреслити моменти, з якими у вас можуть виникнути проблеми.
В англійській (та багатьох інших мовах) імператив використовується для надання команд. Так само у програмуванні імперативний стиль - це той, який надає комп'ютеру набір інструкцій, щоб виконати завдання.
Часто інструкції змінюють статус програми, як, наприклад, оновлення глобальних змінних. Типовий приклад - написання циклу `for`, який дає точні вказівки для ітерації по індексам масиву.
У той же час функціональне програмування - це форма декларативного програмування. Ви вказуєте комп'ютеру, що потрібно зробити, викликаючи метод чи функцію.
JavaScript пропонує багато попередньо визначених методів, які оброблюють загальні завдання. Тому вам не потрібно прописувати, як комп'ютер має виконати їх. Наприклад, замість використання циклу `for` згаданого вище, ви можете викликати метод `map`, який оброблює деталі ітерації по індексам масиву. Це допомагає уникнути смислових помилок, таких як, наприклад, "Помилка неврахованої одиниці", про які йшлося в розділі "Debugging".
Розглянемо ситуацію: ви переглядаєте веб-сторінки і хочете відслідковувати відкриті вкладки. Змоделюємо це, використовуючи звичайний об'єктно-орієнтований код.
Об'єкт Window складається з вкладок і, як правило, їх відкрито декілька. Назви кожного відкритого сайту в кожному об'єкті Window зберігаються в масиві. Після роботи в браузері (відкриття та закриття вкладок, об'єднанні вікон) ви хочете роздрукувати вкладки, які все ще відкриті. Закриті вкладки видаляються з масиву, а нові (для спрощення) додаються в кінець.
Редактор коду показує реалізацію цієї функціональності з функціями: `tabOpen()`, `tabClose()`, and `join()`. Масив `tabs` - це частина об'єкту Window, яка зберігає назви відкритих сторінок.
# --instructions--
Перевірте код у редакторі. Метод, який він використовує, має побічні ефекти у програмі та спричиняє некоректну поведінку. Остаточний список відкритих вкладок, збережених у `finalTabs.tabs`, має бути `['FB', 'Gitter', 'Reddit', 'Twitter', 'Medium', 'new tab', 'Netflix', 'YouTube', 'Vine', 'GMail', 'Work mail', 'Docs', 'freeCodeCamp', 'new tab']`, але список, створений кодом, трохи відрізняється.
Змініть `Window.prototype.tabClose`, щоб видалити правильну вкладку.
# --hints--
`finalTabs.tabs` мають бути `['FB', 'Gitter', 'Reddit', 'Twitter', 'Medium', 'new tab', 'Netflix', 'YouTube', 'Vine', 'GMail', 'Work mail', 'Docs', 'freeCodeCamp', 'new tab']`
```js
assert.deepEqual(finalTabs.tabs, [
'FB',
'Gitter',
'Reddit',
'Twitter',
'Medium',
'new tab',
'Netflix',
'YouTube',
'Vine',
'GMail',
'Work mail',
'Docs',
'freeCodeCamp',
'new tab'
]);
```
# --seed--
## --seed-contents--
```js
// tabs is an array of titles of each site open within the window
const Window = function(tabs) {
this.tabs = tabs; // We keep a record of the array inside the object
};
// When you join two windows into one window
Window.prototype.join = function(otherWindow) {
this.tabs = this.tabs.concat(otherWindow.tabs);
return this;
};
// When you open a new tab at the end
Window.prototype.tabOpen = function(tab) {
this.tabs.push('new tab'); // Let's open a new tab for now
return this;
};
// When you close a tab
Window.prototype.tabClose = function(index) {
// Only change code below this line
const tabsBeforeIndex = this.tabs.splice(0, index); // Get the tabs before the tab
const tabsAfterIndex = this.tabs.splice(index + 1); // Get the tabs after the tab
this.tabs = tabsBeforeIndex.concat(tabsAfterIndex); // Join them together
// Only change code above this line
return this;
};
// Let's create three browser windows
const workWindow = new Window(['GMail', 'Inbox', 'Work mail', 'Docs', 'freeCodeCamp']); // Your mailbox, drive, and other work sites
const socialWindow = new Window(['FB', 'Gitter', 'Reddit', 'Twitter', 'Medium']); // Social sites
const videoWindow = new Window(['Netflix', 'YouTube', 'Vimeo', 'Vine']); // Entertainment sites
// Now perform the tab opening, closing, and other operations
const finalTabs = socialWindow
.tabOpen() // Open a new tab for cat memes
.join(videoWindow.tabClose(2)) // Close third tab in video window, and join
.join(workWindow.tabClose(1).tabOpen());
console.log(finalTabs.tabs);
```
# --solutions--
```js
const Window = function(tabs) {
this.tabs = tabs;
};
Window.prototype.join = function(otherWindow) {
this.tabs = this.tabs.concat(otherWindow.tabs);
return this;
};
Window.prototype.tabOpen = function(tab) {
this.tabs.push('new tab');
return this;
};
Window.prototype.tabClose = function(index) {
const tabsBeforeIndex = this.tabs.slice(0, index);
const tabsAfterIndex = this.tabs.slice(index + 1);
this.tabs = tabsBeforeIndex.concat(tabsAfterIndex);
return this;
};
const workWindow = new Window(['GMail', 'Inbox', 'Work mail', 'Docs', 'freeCodeCamp']);
const socialWindow = new Window(['FB', 'Gitter', 'Reddit', 'Twitter', 'Medium']);
const videoWindow = new Window(['Netflix', 'YouTube', 'Vimeo', 'Vine']);
const finalTabs = socialWindow
.tabOpen()
.join(videoWindow.tabClose(2))
.join(workWindow.tabClose(1).tabOpen());
```