Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 30 additions & 30 deletions 1-js/05-data-types/04-array/article.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

Об’єкти дозволяють зберігати набори значень з ключами. Це чудово.

Але досить часто ми розуміємо, що нам необхідна впорядкована колекція даних, яка складається з 1-го, 2-го, 3-го і т.п елементів. Наприклад, така колеція може знадобитись для зберігання списку користувачів, товарів, HTML елементів та ін.
Але досить часто ми розуміємо, що нам необхідна впорядкована колекція даних, яка складається з 1-го, 2-го, 3-го і т.д. елементів. Наприклад, така колеція може знадобитись для зберігання списку користувачів, товарів, HTML елементів та ін.

Використовувати об’єкти в такому випадку не зручно, тому що вони не надають методів управління порядком елементів. Ми не можемо вставити нову властивість "між" існуючих. Об’єкти просто не призначені для такого.
Використовувати об’єкти в такому випадку не зручно, тому що вони не надають методів управління порядком елементів. Ми не можемо вставити нову властивість "між" існуючих. Об’єкти просто не призначені для цього.

Для зберігання впорядкованих колекцій існує інший тип даних, який має назву масив, `Array`.

Expand All @@ -25,7 +25,7 @@ let fruits = ["Apple", "Orange", "Plum"];

Елементи масиву нумеруються починаючи з нуля.

Ми можемо отримати елементи масиву, вказавши його номер в квадратних дужках:
Ми можемо отримати елемент масиву, вказавши його номер в квадратних дужках:

```js run
let fruits = ["Apple", "Orange", "Plum"];
Expand Down Expand Up @@ -63,7 +63,7 @@ let fruits = ["Apple", "Orange", "Plum"];
alert( fruits ); // Apple,Orange,Plum
```

У масиви можуть зберігатись елементи будь-якого типу.
У масивах можуть зберігатись елементи будь-якого типу.

Наприклад:

Expand All @@ -89,7 +89,7 @@ let fruits = [
];
```

Кома в кінці спрощує процес додавання/видалення елементів, тому що всі рядки стають ідентичними.
Кома в кінці спрощує процес додавання/видалення елементів, тому що всі рядки стають однотипними.
````


Expand All @@ -98,7 +98,7 @@ let fruits = [
[Черга](https://uk.wikipedia.org/wiki/Черга_(структура_даних)) — один з найбільш популярних варіантів використання об’єкту. У ком’ютерних науках так позначають колекцію елементів, яка підтримує дві операції:

- `push` додає елемент у кінець списку.
- `shift` видаляє елемент на початку, зміщчуючи чергу, таким чином другий елемент стає першим.
- `shift` видаляє елемент на початку, зміщчуючи чергу, таким чином, що 2-й елемент стає 1-м.

![](queue.svg)

Expand All @@ -111,7 +111,7 @@ let fruits = [
Вона підтримує два типи операцій:

- `push` додає елементи в кінець.
- `pop` видаляє крайній елемент.
- `pop` видаляє елемент з кінця.

Таким чином нові елементи завжди додаються або видаляються з "кінця".

Expand Down Expand Up @@ -159,7 +159,7 @@ let fruits = [
```js run
let fruits = ["Apple", "Orange", "Pear"];

alert( fruits.shift() ); // видаляємо Apple and виводимо його
alert( fruits.shift() ); // видаляємо Apple та виводимо його
Comment thread
dolgachio marked this conversation as resolved.

alert( fruits ); // Orange, Pear
```
Expand Down Expand Up @@ -189,11 +189,11 @@ alert( fruits );

## Внутрішня структура масивів

Масив це спеціальний тип об’єктів. Квадратні дужки використовують для доступу до властивості `arr[0]`, що в свою чергу прийшло з синтаксису об’єктів. Це теж саме, що доступ до властивості об’єкта `obj[key]`, де `arr` це об’єкт в якому числа використовуються як ключі.
Масив -- це спеціальний вид об’єктів. Квадратні дужки використовують для доступу до властивості `arr[0]`, що в свою чергу прийшло з синтаксису об’єктів. Це теж саме, що доступ до властивості об’єкта `obj[key]`, де `arr` це об’єкт в якому числа використовуються як ключі.

Масиви розширюють функціональність об’єкта тим, що надають можливість працювати з упорядкованими колекціями даних, а також надають доступ до властивості `length`. Але в основі це досі об’єкт.

Запам’ятайте, JavaScript містить лише 8 базових типів даних (більше інформації у розділі [Типи даних](info:types)). Масив це об’єкт, який веде себе як об’єкт.
Запам’ятайте, JavaScript містить лише 8 базових типів даних (більше інформації у розділі [Типи даних](info:types)). Масив -- це об’єкт, який поводить себе як об’єкт.

Наприклад, копіюється за посиланням:

Expand All @@ -209,7 +209,7 @@ arr.push("Pear"); // зміна масиву за посиланням
alert( fruits ); // Banana, Pear - наразі два елемента
```

...Але те, що робить масиви дійсно особливими – це їх внутрішнє представлення. Рушій JavaScript намагається зберігати елементи масиву у неперервній області пам’яті, один за одним, як це представлено на ілюстраціях в цьому розділі, а також інші способи оптимізації, що дозволяють масивам працювати дуже швидко.
...Але те, що робить масиви дійсно особливими – це їх внутрішнє представлення. Рушій JavaScript намагається зберігати елементи масиву у неперервній області пам’яті, один за одним, як це представлено на ілюстраціях в цьому розділі, а також застосовує інші способи оптимізації, що дозволяють масивам працювати дуже швидко.

Проте масиви втратять всю свою ефективність, якщо ми перестанемо працювати з ними як з "упорядкованою колекцією даних" і почнемо використовувати як звичайний об’єкт.

Expand All @@ -230,14 +230,14 @@ fruits.age = 25; // створюємо властивість з довільн
Варіанти неправильного використання масивів:

- Додавання нечислових властивостей, таких як `arr.test = 5`.
- Створення "дирок", наприклад: `arr[0]` а за ним `arr[1000]` (та нічого між цими елементами).
- Створення "дірок", наприклад: `arr[0]` а за ним `arr[1000]` (та нічого між цими елементами).
- Заповнення масиву в зворотньому порядку, наприклад: `arr[1000]`, `arr[999]` і т. д.

Будь ласка, думайте про масив як про особливу структуру з "впорядкованими даними". Вони надають спеціальні методи для цього. Масиви дуже ретельно налаштовані на роботу з неперервними впорядкованими даними, тому використовуйте їх саме таким чином. Тому, якщо вам необхідні довільні ключі, дуже ймовірно, що вам більше підійдуть звичайні об’єкти `{}`.
Будь ласка, думайте про масиви як про особливі структури для роботи з _впорядкованими даними_. Вони надають спеціальні методи для цього. Масиви дуже ретельно налаштовані на роботу з неперервними впорядкованими даними, тому використовуйте їх саме таким чином. Тому, якщо вам необхідні довільні ключі, дуже ймовірно, що вам більше підійдуть звичайні об’єкти `{}`.

## Продуктивність

Методи `push/pop` працюють швидко, на відміну від методів `shift/unshift` які працюють повільно.
Методи `push/pop` працюють швидко, на відміну від методів `shift/unshift`, які працюють повільно.

![](array-speed.svg)

Expand All @@ -247,7 +247,7 @@ fruits.age = 25; // створюємо властивість з довільн
fruits.shift(); // видалити один елемент з початку
```

Але недостатньо просто взяти та видалити елемент з номером `0`. В такому випадку всі інші елементи також необхідно пронумерувати ще раз.
Але недостатньо просто взяти та видалити елемент з номером `0`. Всі інші елементи також необхідно пронумерувати ще раз.

Операція `shift` має виконати 3 дії:

Expand All @@ -261,7 +261,7 @@ fruits.shift(); // видалити один елемент з початку

Теж саме відбувається з методом `unshift`: для того, щоб додати елемент в початок масиву, необхідно спочатку перемістити всі елементи масиву вправо збільшуючи їх індекси.

А що щодо методів `push/pop`? Вони нічого не переміщують. Для видалення елементу з кінця масиву метод `pop` очищає індекс та скорочує властивість `length`.
А як щодо методів `push/pop`? Вони нічого не переміщують. Для видалення елементу з кінця масиву метод `pop` очищає індекс та скорочує властивість `length`.

Дії при операції `pop`:

Expand Down Expand Up @@ -316,18 +316,18 @@ for (let key in arr) {

Але насправді це погана ідея. Існують потеційні проблеми:

1. Цикл `for..in` ітерується по *всіх властивостям*, не тільки по числових.
1. Цикл `for..in` ітерується по *всіх властивостях*, не тільки по числових.

У браузерах та різних програмних середовищах існують масивоподібні об’єкти, *які виглядають як масив*. Тобто вони мають властивість `length` та індекси, проте вони також містять інші нечислові властивості і методи, які нам часто не потрібні. Цикл `for..in` відобразить і їх. Тому, коли нам необхідно працювати з масивами, ці "екстра" властивості можуть стати проблемою.

2. Цикл `for..in` оптимізований для довільних об’єктів, не для масивів, і тому це в 10-100 разів повільніше. Звісно, це все одно дуже швидко. Збільшення швидкості виконання має значення лише у *вузьких місцях*. Але ми все одно повинні бути обережні з відмінностями.
2. Цикл `for..in` оптимізований для довільних об’єктів, не для масивів, і тому в 10-100 разів повільніше. Звісно, це все одно дуже швидко. Збільшення швидкості виконання має значення лише у *вузьких місцях*. Але ми все одно повинні бути обережні з відмінностями.

Словом, не варто використовувати цикл `for..in` для масивів.


## Декілька слів про "length"

Властивість `length` спрацьовує автоматично, коли масив змінився. Якщо бути точнішим, то `length` відображає не кількість елементів в масиві, а індекс останнього елементу плюс один.
Властивість `length` оновлюється автоматично, коли масив змінився. Якщо бути точнішим, то `length` відображає не кількість елементів в масиві, а індекс останнього елементу плюс один.

Наприклад, один елемент з великим індексом дасть велику довжину:

Expand All @@ -340,18 +340,18 @@ alert( fruits.length ); // 124

Зверніть увагу, що зазвичай ми не використовуємо масив подібним чином.

Інший цікавий момент стосовно властивості `length` - його можна перезаписати.
Інший цікавий момент стосовно властивості `length` -- її можна перезаписати.

Якщо ми вручну збільшимо `length`, нічого цікавого не відбудеться. Але якщо зменшимо, масив стане коротшим, цей процес незворотній, наприклад:
Якщо ми вручну збільшимо `length`, нічого цікавого не відбудеться. Але якщо зменшимо, масив стане коротшим. Цей процес незворотній, наприклад:

```js run
let arr = [1, 2, 3, 4, 5];

arr.length = 2; // зкорочуємо до двох елементів
arr.length = 2; // скорочуємо до двох елементів
alert( arr ); // [1, 2]

arr.length = 5; // повертаємо попередню довжину
alert( arr[3] ); // undefined: the values do not return
arr.length = 5; // повертаємо попередню довжину ...
alert( arr[3] ); // undefined: ..., а видалені значення не повертаються
```

Отож, найпростіший метод очистки масиву це: `arr.length = 0;`.
Expand All @@ -367,7 +367,7 @@ let arr = *!*new Array*/!*("Apple", "Pear", "etc");

Він використовується рідше, адже квадратні дужки коротші `[]`. А також має певну особливість.

Якщо `new Array` викликається з одним аргументом, а саме числом, він створить пустий масив з довжиною, яка дорівнює *цьому числу*.
Якщо `new Array` викликається з одним аргументом, а саме числом, він створить порожній масив з довжиною, яка дорівнює *цьому числу*.
Comment thread
dolgachio marked this conversation as resolved.

Подивімось, як можна завдати собі ведмежої послуги:

Expand All @@ -376,10 +376,10 @@ let arr = new Array(2); // чи створиться масив [2] ?

alert( arr[0] ); // undefined! елементи відсутні.

alert( arr.length ); // length 2
alert( arr.length ); // довжина 2
```

Для того, щоб позбавитись таких сюрпризів, як правило, ми використовуємо квадратні дужки `[]`, якщо тільки ми дійсно не маємо причини для використання методу `new Array`.
Для того, щоб позбутись таких сюрпризів, як правило, ми використовуємо квадратні дужки `[]`, якщо тільки ми дійсно не маємо причини для використання методу `new Array`.

## Багатовимірні масиви

Expand Down Expand Up @@ -417,9 +417,9 @@ alert( [1] + 1 ); // "11"
alert( [1,2] + 1 ); // "1,21"
```

Масиви не мають `Symbol.toPrimitive`, або функціонуючого `valueOf`, вони реалізують лише метод `toString` таким чином, що `[]` стає пустою строкою, `[1]` стає `"1"` або `[1,2]` стає `"1,2"`.
Масиви не мають `Symbol.toPrimitive`, або функціонуючого `valueOf`, вони реалізують лише метод `toString` таким чином, що `[]` стає порожнім рядком, `[1]` стає `"1"` або `[1,2]` стає `"1,2"`.

Коли бінарний оператор `"+"` додає щось до рядка, це конвертується в строку та виглядає наступним чином:
Коли бінарний оператор `"+"` додає щось до рядка, це конвертується в рядок та виглядає наступним чином:

```js run
alert( "" + 1 ); // "1"
Expand Down Expand Up @@ -476,7 +476,7 @@ alert('0' == '' ); // false, тут немає конвертації типів

## Підсумки

Масив це особливий тип об’єкту, створений для зберігання та керування впорядкованих даних.
Масив -- це особливий вид об’єкту, створений для зберігання та обробки _впорядкованих елементів_.

- Оголошення:

Expand Down