140 lines
7.2 KiB
Markdown
140 lines
7.2 KiB
Markdown
![]() |
---
|
|||
|
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());
|
|||
|
```
|