This commit is contained in:
Ilya Kantor 2016-03-04 19:06:22 +03:00
parent e78e527866
commit 05a93ced80
212 changed files with 3213 additions and 3968 deletions

View file

@ -6,7 +6,7 @@
var fruits = ["Яблоко", "Груша", "Слива"];
```
Длина массива этого массива `fruits.length` равна `3`. Здесь "Яблоко" имеет индекс `0`, "Груша" -- индекс `1`, "Слива" -- индекс `2`.
Длина массива этого массива `fruits.length` равна `3`. Здесь "Яблоко" имеет индекс `0`, "Груша" -- индекс `1`, "Слива" -- индекс `2`.
То есть, для массива длины `goods`:

View file

@ -1,9 +1,11 @@
# Получить последний элемент массива
importance: 5
[importance 5]
---
# Получить последний элемент массива
Как получить последний элемент из произвольного массива?
У нас есть массив `goods`. Сколько в нем элементов -- не знаем, но можем прочитать из `goods.length`.
У нас есть массив `goods`. Сколько в нем элементов -- не знаем, но можем прочитать из `goods.length`.
Напишите код для получения последнего элемента `goods`.

View file

@ -3,8 +3,7 @@
Например, для `[-1, 2, 3, -9, 11]`:
```js
//+ no-beautify
```js no-beautify
// Начиная с -1:
-1
-1 + 2
@ -37,8 +36,7 @@
Решение через вложенный цикл:
```js
//+ run
```js run
function getMaxSubSum(arr) {
var maxSum = 0; // если совсем не брать элементов, то сумма 0
@ -74,8 +72,7 @@ alert( getMaxSubSum([100, -9, 2, -3, 5]) ); // 100
# Быстрое решение
```js
//+ run
```js run
function getMaxSubSum(arr) {
var maxSum = 0,
partialSum = 0;
@ -87,7 +84,6 @@ function getMaxSubSum(arr) {
return maxSum;
}
alert( getMaxSubSum([-1, 2, 3, -9]) ); // 5
alert( getMaxSubSum([-1, 2, 3, -9, 11]) ); // 11
alert( getMaxSubSum([-2, -1, 1, 2]) ); // 3
@ -96,6 +92,6 @@ alert( getMaxSubSum([1, 2, 3]) ); // 6
alert( getMaxSubSum([-1, -2, -3]) ); // 0
```
Информацию об алгоритме вы также можете прочитать здесь: [](http://e-maxx.ru/algo/maximum_average_segment) и здесь: [Maximum subarray problem](http://en.wikipedia.org/wiki/Maximum_subarray_problem).
Информацию об алгоритме вы также можете прочитать здесь: <http://e-maxx.ru/algo/maximum_average_segment> и здесь: [Maximum subarray problem](http://en.wikipedia.org/wiki/Maximum_subarray_problem).
Этот алгоритм требует ровно одного прохода по массиву, его сложность имеет оценку `O(n)`.

View file

@ -1,10 +1,12 @@
# Подмассив наибольшей суммы
importance: 2
[importance 2]
---
# Подмассив наибольшей суммы
На входе массив чисел, например: `arr = [1, -2, 3, 4, -9, 6]`.
Задача -- найти непрерывный подмассив `arr`, сумма элементов которого максимальна.
Задача -- найти непрерывный подмассив `arr`, сумма элементов которого максимальна.
Ваша функция должна возвращать только эту сумму.
@ -13,7 +15,7 @@
```js
getMaxSubSum([-1, *!*2, 3*/!*, -9]) = 5 (сумма выделенных)
getMaxSubSum([*!*2, -1, 2, 3*/!*, -9]) = 6
getMaxSubSum([-1, 2, 3, -9, *!*11*/!*]) = 11
getMaxSubSum([-1, 2, 3, -9, *!*11*/!*]) = 11
getMaxSubSum([-2, -1, *!*1, 2*/!*]) = 3
getMaxSubSum([*!*100*/!*, -9, 2, -3, 5]) = 100
getMaxSubSum([*!*1, 2, 3*/!*]) = 6 (неотрицательные - берем всех)

View file

@ -1,6 +1,8 @@
# Добавить новый элемент в массив
importance: 5
[importance 5]
---
# Добавить новый элемент в массив
Как добавить элемент в конец произвольного массива?

View file

@ -1,7 +1,6 @@
```js
//+ run
```js run
var styles = ["Джаз", "Блюз"];
styles.push("Рок-н-Ролл");
styles[styles.length - 2] = "Классика";

View file

@ -1,20 +1,20 @@
importance: 5
---
# Создание массива
[importance 5]
Задача из 5 шагов-строк:
<ol>
<li>Создайте массив `styles` с элементами "Джаз", "Блюз".</li>
<li>Добавьте в конец значение "Рок-н-Ролл"</li>
<li>Замените предпоследнее значение с конца на "Классика". Код замены предпоследнего значения должен работать для массивов любой длины.</li>
<li>Удалите первое значение массива и выведите его `alert`.</li>
<li>Добавьте в начало значения "Рэп" и "Регги".</li>
</ol>
1. Создайте массив `styles` с элементами "Джаз", "Блюз".
2. Добавьте в конец значение "Рок-н-Ролл"
3. Замените предпоследнее значение с конца на "Классика". Код замены предпоследнего значения должен работать для массивов любой длины.
4. Удалите первое значение массива и выведите его `alert`.
5. Добавьте в начало значения "Рэп" и "Регги".
Массив в результате каждого шага:
```js
//+ no-beautify
```js no-beautify
Джаз, Блюз
Джаз, Блюз, Рок-н-Ролл
Джаз, Классика, Рок-н-Ролл

View file

@ -1,7 +1,6 @@
Для вывода нужен случайный номер от `0` до `arr.length-1` включительно.
```js
//+ run
```js run
var arr = ["Яблоко", "Апельсин", "Груша", "Лимон"];
var rand = Math.floor(Math.random() * arr.length);

View file

@ -1,6 +1,8 @@
# Получить случайное значение из массива
importance: 3
[importance 3]
---
# Получить случайное значение из массива
Напишите код для вывода `alert` случайного значения из массива:

View file

@ -1,7 +1,6 @@
В решение ниже обратите внимание: мы не приводим `value` к числу сразу после `prompt`, так как если сделать `value = +value`, то после этого отличить пустую строку от нуля уже никак нельзя. А нам здесь нужно при пустой строке прекращать ввод, а при нуле -- продолжать.
```js
//+ run demo
```js run demo
var numbers = [];
while (true) {

View file

@ -1,13 +1,14 @@
# Создайте калькулятор для введённых значений
importance: 4
[importance 4]
---
Напишите код, который:
<ul>
<li>Запрашивает по очереди значения при помощи `prompt` и сохраняет их в массиве.</li>
<li>Заканчивает ввод, как только посетитель введёт пустую строку, не число или нажмёт "Отмена".</li>
<li>При этом ноль `0` не должен заканчивать ввод, это разрешённое число.</li>
<li>Выводит сумму всех значений массива</li>
</ul>
# Создайте калькулятор для введённых значений
[demo /]
Напишите код, который:
- Запрашивает по очереди значения при помощи `prompt` и сохраняет их в массиве.
- Заканчивает ввод, как только посетитель введёт пустую строку, не число или нажмёт "Отмена".
- При этом ноль `0` не должен заканчивать ввод, это разрешённое число.
- Выводит сумму всех значений массива
[demo]

View file

@ -1,7 +1,6 @@
```js
//+ run
```js run
var arr = [1, 2, 3];
var arr2 = arr; // (*)

View file

@ -1,6 +1,8 @@
# Чему равен элемент массива?
importance: 3
[importance 3]
---
# Чему равен элемент массива?
Что выведет этот код?

View file

@ -11,12 +11,11 @@ function find(array, value) {
}
```
Однако, в нем ошибка, т.к. сравнение `==` не различает `0` и `false`.
Однако, в нем ошибка, т.к. сравнение `==` не различает `0` и `false`.
Поэтому лучше использовать `===`. Кроме того, в современном стандарте JavaScript существует встроенная функция <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf">Array#indexOf</a>, которая работает именно таким образом. Имеет смысл ей воспользоваться, если браузер ее поддерживает.
```js
//+ run
```js run
function find(array, value) {
if (array.indexOf) { // если метод существует
return array.indexOf(value);

View file

@ -1,6 +1,8 @@
# Поиск в массиве
importance: 3
[importance 3]
---
# Поиск в массиве
Создайте функцию `find(arr, value)`, которая ищет в массиве `arr` значение `value` и возвращает его номер, если найдено, или `-1`, если не найдено.

View file

@ -1,14 +1,12 @@
# Алгоритм решения
<ol>
<li>Создайте временный пустой массив `var results = []`. </li>
<li>Пройдите по элементам `arr` в цикле и заполните его.</li>
<li>Возвратите `results`.</li>
</ol>
1. Создайте временный пустой массив `var results = []`.
2. Пройдите по элементам `arr` в цикле и заполните его.
3. Возвратите `results`.
# Решение
```js
//+ run
```js run
function filterRange(arr, a, b) {
var result = [];

View file

@ -1,8 +1,10 @@
importance: 3
---
# Фильтр диапазона
[importance 3]
Создайте функцию `filterRange(arr, a, b)`, которая принимает массив чисел `arr` и возвращает новый массив, который содержит только числа из `arr` из диапазона от `a` до `b`. То есть, проверка имеет вид `a ≤ arr[i] ≤ b`.
Создайте функцию `filterRange(arr, a, b)`, которая принимает массив чисел `arr` и возвращает новый массив, который содержит только числа из `arr` из диапазона от `a` до `b`. То есть, проверка имеет вид `a ≤ arr[i] ≤ b`.
Функция не должна менять `arr`.
Пример работы:

View file

@ -1,7 +1,6 @@
Их сумма равна `1060`.
```js
//+ run
```js run
// шаг 1
var arr = [];

View file

@ -1,19 +1,19 @@
# Решето Эратосфена
importance: 3
[importance 3]
---
# Решето Эратосфена
Целое число, большее `1`, называется *простым*, если оно не делится нацело ни на какое другое, кроме себя и `1`.
Древний алгоритм "Решето Эратосфена" для поиска всех простых чисел до `n` выглядит так:
<ol>
<li>Создать список последовательных чисел от `2` до `n`: `2, 3, 4, ..., n`.</li>
<li>Пусть `p=2`, это первое простое число.</li>
<li>Зачеркнуть все последующие числа в списке с разницей в `p`, т.е. `2*p, 3*p, 4*p` и т.д. В случае `p=2` это будут `4,6,8...`.</li>
<li>Поменять значение `p` на первое не зачеркнутое число после `p`.</li>
<li>Повторить шаги 3-4 пока <code>p<sup>2</sup> &lt; n</code>.</li>
<li>Все оставшиеся не зачеркнутыми числа -- простые.</li>
</ol>
1. Создать список последовательных чисел от `2` до `n`: `2, 3, 4, ..., n`.
2. Пусть `p=2`, это первое простое число.
3. Зачеркнуть все последующие числа в списке с разницей в `p`, т.е. `2*p, 3*p, 4*p` и т.д. В случае `p=2` это будут `4,6,8...`.
4. Поменять значение `p` на первое не зачеркнутое число после `p`.
5. Повторить шаги 3-4 пока <code>p<sup>2</sup> &lt; n</code>.
6. Все оставшиеся не зачеркнутыми числа -- простые.
Посмотрите также [анимацию алгоритма](sieve.gif).
@ -21,5 +21,3 @@
Найдите все простые числа до `100` и выведите их сумму.

View file

@ -8,7 +8,7 @@
## Объявление
Синтаксис для создания нового массива -- квадратные скобки со списком элементов внутри.
Синтаксис для создания нового массива -- квадратные скобки со списком элементов внутри.
Пустой массив:
@ -22,12 +22,11 @@ var arr = [];
var fruits = ["Яблоко", "Апельсин", "Слива"];
```
**Элементы нумеруются, начиная с нуля.**
**Элементы нумеруются, начиная с нуля.**
Чтобы получить нужный элемент из массива -- указывается его номер в квадратных скобках:
```js
//+ run
```js run
var fruits = ["Яблоко", "Апельсин", "Слива"];
alert( fruits[0] ); // Яблоко
@ -49,30 +48,27 @@ fruits[3] = 'Лимон'; // теперь ["Яблоко", "Апельсин", "
Общее число элементов, хранимых в массиве, содержится в его свойстве `length`:
```js
//+ run
```js run
var fruits = ["Яблоко", "Апельсин", "Груша"];
alert( fruits.length ); // 3
```
**Через `alert` можно вывести и массив целиком.**
**Через `alert` можно вывести и массив целиком.**
При этом его элементы будут перечислены через запятую:
```js
//+ run
```js run
var fruits = ["Яблоко", "Апельсин", "Груша"];
alert( fruits ); // Яблоко,Апельсин,Груша
```
**В массиве может храниться любое число элементов любого типа.**
**В массиве может храниться любое число элементов любого типа.**
В том числе, строки, числа, объекты, вот например:
```js
//+ run no-beautify
```js run no-beautify
// микс значений
var arr = [ 1, 'Имя', { name: 'Петя' }, true ];
@ -80,17 +76,17 @@ var arr = [ 1, 'Имя', { name: 'Петя' }, true ];
alert( arr[2].name ); // Петя
```
## Методы pop/push, shift/unshift
## Методы pop/push, shift/unshift
Одно из применений массива -- это [очередь](http://ru.wikipedia.org/wiki/%D0%9E%D1%87%D0%B5%D1%80%D0%B5%D0%B4%D1%8C_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%29). В классическом программировании так называют упорядоченную коллекцию элементов, такую что элементы добавляются в конец, а обрабатываются -- с начала.
Одно из применений массива -- это [очередь](http://ru.wikipedia.org/wiki/%D0%9E%D1%87%D0%B5%D1%80%D0%B5%D0%B4%D1%8C_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%29). В классическом программировании так называют упорядоченную коллекцию элементов, такую что элементы добавляются в конец, а обрабатываются -- с начала.
<img src="queue.png">
![](queue.png)
В реальной жизни эта структура данных встречается очень часто. Например, очередь сообщений, которые надо показать на экране.
Очень близка к очереди еще одна структура данных: [стек](http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D0%B5%D0%BA). Это такая коллекция элементов, в которой новые элементы добавляются в конец и берутся с конца.
Очень близка к очереди еще одна структура данных: [стек](http://ru.wikipedia.org/wiki/%D0%A1%D1%82%D0%B5%D0%BA). Это такая коллекция элементов, в которой новые элементы добавляются в конец и берутся с конца.
<img src="stack.png">
![](stack.png)
Например, стеком является колода карт, в которую новые карты кладутся сверху, и берутся -- тоже сверху.
@ -98,69 +94,57 @@ alert( arr[2].name ); // Петя
### Конец массива
<dl>
<dt>`pop`</dt>
<dd>Удаляет *последний* элемент из массива и возвращает его:
`pop`
: Удаляет *последний* элемент из массива и возвращает его:
```js
//+ run
var fruits = ["Яблоко", "Апельсин", "Груша"];
```js run
var fruits = ["Яблоко", "Апельсин", "Груша"];
alert( fruits.pop() ); // удалили "Груша"
alert( fruits.pop() ); // удалили "Груша"
alert( fruits ); // Яблоко, Апельсин
```
alert( fruits ); // Яблоко, Апельсин
```
</dd>
<dt>`push`</dt>
<dd>Добавляет элемент *в конец* массива:
`push`
: Добавляет элемент *в конец* массива:
```js
//+ run
var fruits = ["Яблоко", "Апельсин"];
```js run
var fruits = ["Яблоко", "Апельсин"];
fruits.push("Груша");
fruits.push("Груша");
alert( fruits ); // Яблоко, Апельсин, Груша
```
alert( fruits ); // Яблоко, Апельсин, Груша
```
Вызов `fruits.push(...)` равнозначен `fruits[fruits.length] = ...`.
</dd>
</dl>
Вызов `fruits.push(...)` равнозначен `fruits[fruits.length] = ...`.
### Начало массива
<dl>
<dt>`shift`</dt>
<dd>Удаляет из массива *первый* элемент и возвращает его:
`shift`
: Удаляет из массива *первый* элемент и возвращает его:
```js
var fruits = ["Яблоко", "Апельсин", "Груша"];
```js
var fruits = ["Яблоко", "Апельсин", "Груша"];
alert( fruits.shift() ); // удалили Яблоко
alert( fruits.shift() ); // удалили Яблоко
alert( fruits ); // Апельсин, Груша
```
alert( fruits ); // Апельсин, Груша
```
</dd>
<dt>`unshift`</dt>
<dd>Добавляет элемент *в начало* массива:
`unshift`
: Добавляет элемент *в начало* массива:
```js
var fruits = ["Апельсин", "Груша"];
```js
var fruits = ["Апельсин", "Груша"];
fruits.unshift('Яблоко');
fruits.unshift('Яблоко');
alert( fruits ); // Яблоко, Апельсин, Груша
```
</dd>
</dl>
alert( fruits ); // Яблоко, Апельсин, Груша
```
Методы `push` и `unshift` могут добавлять сразу по несколько элементов:
```js
//+ run
```js run
var fruits = ["Яблоко"];
fruits.push("Апельсин", "Персик");
@ -176,8 +160,7 @@ alert( fruits );
Так как это объект, то в функцию он передаётся по ссылке:
```js
//+ run
```js run
function eat(arr) {
arr.pop();
}
@ -202,15 +185,14 @@ fruits[99999] = 5; // присвоить свойство с любым номе
fruits.age = 25; // назначить свойство со строковым именем
```
.. Но массивы для того и придуманы в JavaScript, чтобы удобно работать именно *с упорядоченными, нумерованными данными*. Для этого в них существуют специальные методы и свойство `length`.
.. Но массивы для того и придуманы в JavaScript, чтобы удобно работать именно *с упорядоченными, нумерованными данными*. Для этого в них существуют специальные методы и свойство `length`.
Как правило, нет причин использовать массив как обычный объект, хотя технически это и возможно.
[warn header="Вывод массива с \"дырами\""]
````warn header="Вывод массива с \"дырами\""
Если в массиве есть пропущенные индексы, то при выводе в большинстве браузеров появляются "лишние" запятые, например:
```js
//+ run
```js run
var a = [];
a[0] = 0;
a[5] = 5;
@ -219,14 +201,13 @@ alert( a ); // 0,,,,,5
```
Эти запятые появляются потому, что алгоритм вывода массива идёт от `0` до `arr.length` и выводит всё через запятую. Отсутствие значений даёт несколько запятых подряд.
[/warn]
````
### Влияние на быстродействие
Методы `push/pop` выполняются быстро, а `shift/unshift` -- медленно.
<img src="array-speed.png">
![](array-speed.png)
Чтобы понять, почему работать с концом массива -- быстрее, чем с его началом, разберём подробнее происходящее при операции:
@ -237,13 +218,12 @@ fruits.shift(); // убрать 1 элемент с начала
При этом, так как все элементы находятся в своих ячейках, просто удалить элемент с номером `0` недостаточно. Нужно еще и переместить остальные элементы на их новые индексы.
Операция `shift` должна выполнить целых три действия:
<ol>
<li>Удалить нулевой элемент.</li>
<li>Переместить все свойства влево, с индекса `1` на `0`, с `2` на `1` и так далее.</li>
<li>Обновить свойство `length`.</li>
</ol>
<img src="array-shift.png">
1. Удалить нулевой элемент.
2. Переместить все свойства влево, с индекса `1` на `0`, с `2` на `1` и так далее.
3. Обновить свойство `length`.
![](array-shift.png)
**Чем больше элементов в массиве, тем дольше их перемещать, это много операций с памятью.**
@ -257,19 +237,17 @@ fruits.shift(); // убрать 1 элемент с начала
fruits.pop(); // убрать 1 элемент с конца
```
<img src="array-pop.png">
![](array-pop.png)
**Перемещать при `pop` не требуется, так как прочие элементы после этой операции остаются на тех же индексах.**
Аналогично работает `push`.
## Перебор элементов
Для перебора элементов обычно используется цикл:
```js
//+ run
```js run
var arr = ["Яблоко", "Апельсин", "Груша"];
*!*
@ -279,11 +257,10 @@ for (var i = 0; i < arr.length; i++) {
*/!*
```
[warn header="Не используйте `for..in` для массивов"]
````warn header="Не используйте `for..in` для массивов"
Так как массив является объектом, то возможен и вариант `for..in`:
```js
//+ run
```js run
var arr = ["Яблоко", "Апельсин", "Груша"];
*!*
@ -295,32 +272,27 @@ for (var key in arr) {
Недостатки этого способа:
<ol>
<li>Цикл `for..in` выведет *все свойства* объекта, а не только цифровые.
1. Цикл `for..in` выведет *все свойства* объекта, а не только цифровые.
В браузере, при работе с объектами страницы, встречаются коллекции элементов, которые по виду как массивы, но имеют дополнительные нецифровые свойства. При переборе таких "похожих на массив" коллекций через `for..in` эти свойства будут выведены, а они как раз не нужны.
В браузере, при работе с объектами страницы, встречаются коллекции элементов, которые по виду как массивы, но имеют дополнительные нецифровые свойства. При переборе таких "похожих на массив" коллекций через `for..in` эти свойства будут выведены, а они как раз не нужны.
Бывают и библиотеки, которые предоставляют такие коллекции. Классический `for` надёжно выведет только цифровые свойства, что обычно и требуется.
</li>
<li>Цикл `for (var i=0; i<arr.length; i++)` в современных браузерах выполняется в 10-100 раз быстрее. Казалось бы, по виду он сложнее, но браузер особым образом оптимизирует такие циклы.</li>
</ol>
Бывают и библиотеки, которые предоставляют такие коллекции. Классический `for` надёжно выведет только цифровые свойства, что обычно и требуется.
2. Цикл `for (var i=0; i<arr.length; i++)` в современных браузерах выполняется в 10-100 раз быстрее. Казалось бы, по виду он сложнее, но браузер особым образом оптимизирует такие циклы.
Если коротко: цикл `for(var i=0; i<arr.length...)` надёжнее и быстрее.
[/warn]
````
## Особенности работы length
Встроенные методы для работы с массивом автоматически обновляют его длину `length`.
**Длина `length` -- не количество элементов массива, а `последний индекс + 1`**.
**Длина `length` -- не количество элементов массива, а `последний индекс + 1`**.
Так уж оно устроено.
Это легко увидеть на следующем примере:
```js
//+ run
```js run
var arr = [];
arr[1000] = true;
@ -331,14 +303,13 @@ alert(arr.length); // *!*1001*/!*
### Используем length для укорачивания массива
Обычно нам не нужно самостоятельно менять `length`... Но есть один фокус, который можно провернуть.
Обычно нам не нужно самостоятельно менять `length`... Но есть один фокус, который можно провернуть.
**При уменьшении `length` массив укорачивается.**
**При уменьшении `length` массив укорачивается.**
Причем этот процесс необратимый, т.е. даже если потом вернуть `length` обратно -- значения не восстановятся:
```js
//+ run
```js run
var arr = [1, 2, 3, 4, 5];
arr.length = 2; // укоротить до 2 элементов
@ -349,10 +320,10 @@ alert( arr[3] ); // undefined: значения не вернулись
```
Самый простой способ очистить массив -- это `arr.length=0`.
## Создание вызовом new Array [#new-array]
### new Array()
### new Array()
Существует еще один синтаксис для создания массива:
```js
@ -365,8 +336,7 @@ var arr = *!*new Array*/!*("Яблоко", "Груша", "и т.п.");
Проверим это:
```js
//+ run
```js run
var arr = new Array(2, 3);
alert( arr[0] ); // 2, создан массив [2, 3], всё ок
@ -382,12 +352,11 @@ alert( arr[0] ); // undefined! у нас массив без элементов,
Это может быть неожиданным сюрпризом, поэтому обычно используют квадратные скобки.
### Многомерные массивы
### Многомерные массивы
Массивы в JavaScript могут содержать в качестве элементов другие массивы. Это можно использовать для создания многомерных массивов, например матриц:
```js
//+ run
```js run
var matrix = [
[1, 2, 3],
[4, 5, 6],
@ -399,30 +368,28 @@ alert( matrix[1][1] ); // центральный элемент
## Внутреннее представление массивов
[warn header="Hardcore coders only"]
```warn header="Hardcore coders only"
Эта секция относится ко внутреннему устройству структуры данных и требует специальных знаний. Она не обязательна к прочтению.
[/warn]
```
Числовые массивы, согласно спецификации, являются объектами, в которые добавили ряд свойств, методов и автоматическую длину `length`. Но внутри они, как правило, устроены по-другому.
**Современные интерпретаторы стараются оптимизировать их и хранить в памяти не в виде хэш-таблицы, а в виде непрерывной области памяти, по которой легко пробежаться от начала до конца.**
**Современные интерпретаторы стараются оптимизировать их и хранить в памяти не в виде хэш-таблицы, а в виде непрерывной области памяти, по которой легко пробежаться от начала до конца.**
Операции с массивами также оптимизируются, особенно если массив хранит только один тип данных, например только числа. Порождаемый набор инструкций для процессора получается очень эффективным.
Чтобы у интерпретатора получались эти оптимизации, программист не должен мешать.
Чтобы у интерпретатора получались эти оптимизации, программист не должен мешать.
В частности:
<ul>
<li>Не ставить массиву произвольные свойства, такие как `arr.test = 5`. То есть, работать именно как с массивом, а не как с объектом.</li>
<li>Заполнять массив непрерывно и по возрастающей. Как только браузер встречает необычное поведение массива, например устанавливается значение `arr[0]`, а потом сразу `arr[1000]`, то он начинает работать с ним, как с обычным объектом. Как правило, это влечёт преобразование его в хэш-таблицу.</li>
</ul>
- Не ставить массиву произвольные свойства, такие как `arr.test = 5`. То есть, работать именно как с массивом, а не как с объектом.
- Заполнять массив непрерывно и по возрастающей. Как только браузер встречает необычное поведение массива, например устанавливается значение `arr[0]`, а потом сразу `arr[1000]`, то он начинает работать с ним, как с обычным объектом. Как правило, это влечёт преобразование его в хэш-таблицу.
Если следовать этим принципам, то массивы будут занимать меньше памяти и быстрее работать.
## Итого
Массивы существуют для работы с упорядоченным набором элементов.
Массивы существуют для работы с упорядоченным набором элементов.
**Объявление:**
@ -438,25 +405,19 @@ var arr = new Array(элемент1, элемент2...);
**Свойство `length`** -- длина массива. Если точнее, то последний индекс массива плюс `1`. Если её уменьшить вручную, то массив укоротится. Если `length` больше реального количества элементов, то отсутствующие элементы равны `undefined`.
Массив можно использовать как очередь или стек.
**Операции с концом массива:**
<ul>
<li>`arr.push(элемент1, элемент2...)` добавляет элементы в конец.</li>
<li>`var elem = arr.pop()` удаляет и возвращает последний элемент.</li>
</ul>
- `arr.push(элемент1, элемент2...)` добавляет элементы в конец.
- `var elem = arr.pop()` удаляет и возвращает последний элемент.
**Операции с началом массива:**
<ul>
<li>`arr.unshift(элемент1, элемент2...)` добавляет элементы в начало.</li>
<li>`var elem = arr.shift()` удаляет и возвращает первый элемент.</li>
</ul>
- `arr.unshift(элемент1, элемент2...)` добавляет элементы в начало.
- `var elem = arr.shift()` удаляет и возвращает первый элемент.
Эти операции перенумеровывают все элементы, поэтому работают медленно.
В следующей главе мы рассмотрим другие методы для работы с массивами.