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

@ -1,8 +1,7 @@
Решение заключается в превращении `obj.className` в массив при помощи `split`.
Решение заключается в превращении `obj.className` в массив при помощи `split`.
После этого в нем можно проверить наличие класса, и если нет - добавить.
```js
//+ run
```js run
function addClass(obj, cls) {
var classes = obj.className ? obj.className.split(' ') : [];
@ -25,6 +24,6 @@ addClass(obj, 'me');
alert(obj.className) // open menu new me
```
P.S. "Альтернативный" подход к проверке наличия класса вызовом `obj.className.indexOf(cls)` был бы неверным. В частности, он найдёт `cls = "menu"` в строке классов `obj.className = "open mymenu"`.
P.S. "Альтернативный" подход к проверке наличия класса вызовом `obj.className.indexOf(cls)` был бы неверным. В частности, он найдёт `cls = "menu"` в строке классов `obj.className = "open mymenu"`.
P.P.S. Проверьте, нет ли в вашем решении присвоения `obj.className += " " + cls`. Не добавляет ли оно лишний пробел в случае, если изначально `obj.className = ""`?

View file

@ -1,6 +1,8 @@
# Добавить класс в строку
importance: 5
[importance 5]
---
# Добавить класс в строку
В объекте есть свойство `className`, которое содержит список "классов" - слов, разделенных пробелом:

View file

@ -1,4 +1,4 @@
# Решение
# Решение
Чтобы обнаружить анаграммы, разобьём каждое слово на буквы и отсортируем их. В отсортированном по буквам виде все анаграммы одинаковы.
@ -10,12 +10,11 @@
...
```
По такой последовательности будем делать массив уникальным.
По такой последовательности будем делать массив уникальным.
Для этого воспользуемся вспомогательным объектом, в который будем записывать слова по отсортированному ключу:
```js
//+ run
```js run
function aclean(arr) {
// этот объект будем использовать для уникальности
var obj = {};
@ -49,12 +48,12 @@ alert( aclean(arr) );
```js
var sorted = arr[i] // ЗОВ
.toLowerCase() // зов
.split('') // ['з','о','в']
.split('') // ['з','о','в']
.sort() // ['в','з','о']
.join(''); // взо
```
Получится, что два разных слова `'ЗОВ'` и `'воз'` получат одинаковую отсортированную форму `'взо'`.
Получится, что два разных слова `'ЗОВ'` и `'воз'` получат одинаковую отсортированную форму `'взо'`.
Следующая строка:
@ -62,7 +61,7 @@ var sorted = arr[i] // ЗОВ
obj[sorted] = arr[i];
```
В объект `obj` будет записано сначала первое из слов `obj['взо'] = "воз"`, а затем `obj['взо'] = 'ЗОВ'`.
В объект `obj` будет записано сначала первое из слов `obj['взо'] = "воз"`, а затем `obj['взо'] = 'ЗОВ'`.
Обратите внимание, ключ -- отсортирован, а само слово -- в исходной форме, чтобы можно было потом получить его из объекта.

View file

@ -1,6 +1,8 @@
# Отфильтровать анаграммы
importance: 3
[importance 3]
---
# Отфильтровать анаграммы
*Анаграммы* -- слова, состоящие из одинакового количества одинаковых букв, но в разном порядке.
Например:
@ -11,7 +13,7 @@
корсет - костер - сектор
```
Напишите функцию `aclean(arr)`, которая возвращает массив слов, очищенный от анаграмм.
Напишите функцию `aclean(arr)`, которая возвращает массив слов, очищенный от анаграмм.
Например:
@ -23,5 +25,3 @@ alert( aclean(arr) ); // "воз,киборг,корсет" или "ЗОВ,гр
Из каждой группы анаграмм должно остаться только одно слово, не важно какое.

View file

@ -1,11 +1,10 @@
# Решение перебором (медленное)
Пройдём по массиву вложенным циклом.
Пройдём по массиву вложенным циклом.
Для каждого элемента мы будем искать, был ли такой уже. Если был -- игнорировать:
```js
//+ run
```js run
function unique(arr) {
var result = [];
@ -36,12 +35,10 @@ alert( unique(strings) ); // кришна, харе, 8-()
В этом случае для каждого элемента понадобится обойти весь текущий массив результатов, после чего -- добавить в этот массив.
<ol>
<li>Для первого элемента -- это обойдётся в `0` операций доступа к элементам `result` (он пока пустой).</li>
<li>Для второго элемента -- это обойдётся в `1` операцию доступа к элементам `result`.</li>
<li>Для третьего элемента -- это обойдётся в `2` операции доступа к элементам `result`.</li>
<li>...Для n-го элемента -- это обойдётся в `n-1` операций доступа к элементам `result`.</li>
</ol>
1. Для первого элемента -- это обойдётся в `0` операций доступа к элементам `result` (он пока пустой).
2. Для второго элемента -- это обойдётся в `1` операцию доступа к элементам `result`.
3. Для третьего элемента -- это обойдётся в `2` операции доступа к элементам `result`.
4. ...Для n-го элемента -- это обойдётся в `n-1` операций доступа к элементам `result`.
Всего <code>0 + 1 + 2 + ... + n-1 = (n-1)*n/2 = n<sup>2</sup>/2 - n/2</code> (как сумма арифметической прогрессии), то есть количество операций растёт примерно как квадрат от `n`.
@ -53,12 +50,11 @@ alert( unique(strings) ); // кришна, харе, 8-()
Наилучшая техника для выбора уникальных строк -- использование вспомогательного объекта `obj`. Ведь название свойства в объекте, с одной стороны -- строка, а с другой -- всегда уникально. Повторная запись в свойство с тем же именем перезапишет его.
Например, если `"харе"` попало в объект один раз (`obj["харе"] = true`), то второе такое же присваивание ничего не изменит.
Например, если `"харе"` попало в объект один раз (`obj["харе"] = true`), то второе такое же присваивание ничего не изменит.
Решение ниже создаёт объект `obj = {}` и записывает в него все строки как имена свойств. А затем собирает свойства из объекта в массив через `for..in`. Дубликатов уже не будет.
```js
//+ run
```js run
function unique(arr) {
var obj = {};

View file

@ -1,6 +1,8 @@
# Оставить уникальные элементы массива
importance: 3
[importance 3]
---
# Оставить уникальные элементы массива
Пусть `arr` -- массив строк.

View file

@ -6,8 +6,7 @@
Разобьем строку в массив, а затем преобразуем его элементы и сольём обратно:
```js
//+ run
```js run
function camelize(str) {
var arr = str.split('-');

View file

@ -1,6 +1,8 @@
# Перевести текст вида border-left-width в borderLeftWidth
importance: 3
[importance 3]
---
# Перевести текст вида border-left-width в borderLeftWidth
Напишите функцию `camelize(str)`, которая преобразует строки вида "my-short-string" в "myShortString".
@ -14,7 +16,7 @@ camelize("list-style-image") == 'listStyleImage';
camelize("-webkit-transition") == 'WebkitTransition';
```
Такая функция полезна при работе с CSS.
Такая функция полезна при работе с CSS.
P.S. Вам пригодятся методы строк `charAt`, `split` и `toUpperCase`.

View file

@ -1,13 +1,12 @@
Решение заключается в том, чтобы разбить `className` в массив классов, а затем пройтись по нему циклом. Если класс есть - удаляем его `splice`, заново объединяем массив в строку и присваиваем объекту.
```js
//+ run
```js run
function removeClass(obj, cls) {
var classes = obj.className.split(' ');
for (i = 0; i < classes.length; i++) {
if (classes[i] == cls) {
classes.splice(i, 1); // удалить класс
classes.splice(i, 1); // удалить класс
*!*
i--; // (*)
*/!*
@ -28,6 +27,6 @@ alert(obj.className) // open
В примере выше есть тонкий момент. Элементы массива проверяются один за другим. При вызове `splice` удаляется текущий, `i-й` элемент, и те элементы, которые идут дальше, сдвигаются на его место.
Таким образом, **на месте `i` оказывается новый, непроверенный элемент**.
Таким образом, **на месте `i` оказывается новый, непроверенный элемент**.
Чтобы это учесть, строчка `(*)` уменьшает `i`, чтобы следующая итерация цикла заново проверила элемент с номером `i`. Без нее функция будет работать с ошибками.

View file

@ -1,6 +1,8 @@
# Функция removeClass
importance: 5
[importance 5]
---
# Функция removeClass
У объекта есть свойство `className`, которое хранит список "классов" - слов, разделенных пробелами:

View file

@ -1,7 +1,6 @@
```js
//+ run
```js run
function filterRangeInPlace(arr, a, b) {
for (var i = 0; i < arr.length; i++) {

View file

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

View file

@ -1,7 +1,6 @@
```js
//+ run
```js run
var arr = [5, 2, 1, -10, 8];
function compareReversed(a, b) {

View file

@ -1,6 +1,8 @@
# Сортировать в обратном порядке
importance: 5
[importance 5]
---
# Сортировать в обратном порядке
Как отсортировать массив чисел в обратном порядке?

View file

@ -1,7 +1,6 @@
Для копирования массива используем `slice()`, и тут же -- сортировку:
```js
//+ run
```js run
var arr = ["HTML", "JavaScript", "CSS"];
*!*

View file

@ -1,6 +1,8 @@
# Скопировать и отсортировать массив
importance: 5
[importance 5]
---
# Скопировать и отсортировать массив
Есть массив строк `arr`. Создайте массив `arrSorted` -- из тех же элементов, но отсортированный.

View file

@ -6,8 +6,7 @@
Обычно `Math.random()` возвращает результат от `0` до `1`. Вычтем `0.5`, чтобы область значений стала `[-0.5 ... 0.5)`.
```js
//+ run
```js run
var arr = [1, 2, 3, 4, 5];
*!*

View file

@ -1,6 +1,8 @@
# Случайный порядок в массиве
importance: 3
[importance 3]
---
# Случайный порядок в массиве
Используйте функцию `sort` для того, чтобы "перетрясти" элементы массива в случайном порядке.

View file

@ -1,7 +1,6 @@
Для сортировки объявим и передадим в `sort` анонимную функцию, которая сравнивает объекты по полю `age`:
```js
//+ run no-beautify
```js run no-beautify
*!*
// Наша функция сравнения
function compareAge(personA, personB) {

View file

@ -1,13 +1,14 @@
# Сортировка объектов
importance: 5
[importance 5]
---
# Сортировка объектов
Напишите код, который отсортирует массив объектов `people` по полю `age`.
Например:
```js
//+ no-beautify
```js no-beautify
var vasya = { name: "Вася", age: 23 };
var masha = { name: "Маша", age: 18 };
var vovochka = { name: "Вовочка", age: 6 };

View file

@ -1,7 +1,6 @@
# Вывод списка в цикле
```js
//+ run
```js run
var list = {
value: 1,
next: {
@ -50,8 +49,7 @@ function printList(list) {
Рекурсивный вариант `printList(list)` следует простой логике: вывести текущее значение `(1)`, а затем пропустить через себя следующее `(2)`:
```js
//+ run
```js run
var list = {
value: 1,
next: {
@ -83,8 +81,7 @@ printList(list);
Обратный вывод -- почти то же самое, что прямой, просто сначала мы обрабатываем следующее значение, а потом -- текущее:
```js
//+ run
```js run
var list = {
value: 1,
next: {
@ -113,8 +110,7 @@ printReverseList(list);
# Обратный вывод без рекурсии
```js
//+ run
```js run
var list = {
value: 1,
next: {
@ -129,7 +125,6 @@ var list = {
}
};
function printReverseList(list) {
var arr = [];
var tmp = list;

View file

@ -1,6 +1,8 @@
# Вывести односвязный список
importance: 5
[importance 5]
---
# Вывести односвязный список
[Односвязный список](http://ru.wikipedia.org/wiki/Связный_список) -- это структура данных, которая состоит из *элементов*, каждый из которых хранит ссылку на следующий. Последний элемент может не иметь ссылки, либо она равна `null`.
@ -23,12 +25,11 @@ var list = {
```
Графическое представление этого списка:
<img src="linked-list.png">
![](linked-list.png)
Альтернативный способ создания:
```js
//+ no-beautify
```js no-beautify
var list = { value: 1 };
list.next = { value: 2 };
list.next.next = { value: 3 };
@ -39,12 +40,10 @@ list.next.next.next = { value: 4 };
Задачи:
<ol>
<li>Напишите функцию `printList(list)`, которая выводит элементы списка по очереди, при помощи цикла.</li>
<li>Напишите функцию `printList(list)` при помощи рекурсии.</li>
<li>Напишите функцию `printReverseList(list)`, которая выводит элементы списка в обратном порядке, при помощи рекурсии.
Для списка выше она должна выводить `4`,`3`,`2`,`1`</li>
<li>Сделайте вариант `printReverseList(list)`, использующий не рекурсию, а цикл.</li>
</ol>
1. Напишите функцию `printList(list)`, которая выводит элементы списка по очереди, при помощи цикла.
2. Напишите функцию `printList(list)` при помощи рекурсии.
3. Напишите функцию `printReverseList(list)`, которая выводит элементы списка в обратном порядке, при помощи рекурсии.
Для списка выше она должна выводить `4`,`3`,`2`,`1`
4. Сделайте вариант `printReverseList(list)`, использующий не рекурсию, а цикл.
Как лучше -- с рекурсией или без?

View file

@ -1,16 +1,16 @@
# Массивы: методы
В этой главе мы рассмотрим встроенные методы массивов JavaScript.
[cut]
## Метод split
## Метод split
Ситуация из реальной жизни. Мы пишем сервис отсылки сообщений и посетитель вводит имена тех, кому его отправить: `Маша, Петя, Марина, Василий...`. Но нам-то гораздо удобнее работать с массивом имен, чем с одной строкой.
Ситуация из реальной жизни. Мы пишем сервис отсылки сообщений и посетитель вводит имена тех, кому его отправить: `Маша, Петя, Марина, Василий...`. Но нам-то гораздо удобнее работать с массивом имен, чем с одной строкой.
К счастью, есть метод `split(s)`, который позволяет превратить строку в массив, разбив ее по разделителю `s`. В примере ниже таким разделителем является строка из запятой и пробела.
```js
//+ run
```js run
var names = 'Маша, Петя, Марина, Василий';
var arr = names.split(', ');
@ -20,36 +20,31 @@ for (var i = 0; i < arr.length; i++) {
}
```
[smart header="Второй аргумент `split`"]
````smart header="Второй аргумент `split`"
У метода `split` есть необязательный второй аргумент -- ограничение на количество элементов в массиве. Если их больше, чем указано -- остаток массива будет отброшен:
```js
//+ run
```js run
alert( "a,b,c,d".split(',', *!*2*/!*) ); // a,b
```
````
[/smart]
[smart header="Разбивка по буквам"]
````smart header="Разбивка по буквам"
Вызов `split` с пустой строкой разобьёт по буквам:
```js
//+ run
```js run
var str = "тест";
alert( str.split('') ); // т,е,с
```
````
[/smart]
## Метод join
## Метод join
Вызов `arr.join(str)` делает в точности противоположное `split`. Он берет массив и склеивает его в строку, используя `str` как разделитель.
Например:
```js
//+ run
```js run
var arr = ['Маша', 'Петя', 'Марина', 'Василий'];
var str = arr.join(';');
@ -57,26 +52,23 @@ var str = arr.join(';');
alert( str ); // Маша;Петя;Марина;Василий
```
[smart header="new Array + join = Повторение строки"]
````smart header="new Array + join = Повторение строки"
Код для повторения строки `3` раза:
```js
//+ run
```js run
alert( new Array(4).join("ля") ); // ляляля
```
Как видно, `new Array(4)` делает массив без элементов длины 4, который `join` объединяет в строку, вставляя *между его элементами* строку `"ля"`.
Как видно, `new Array(4)` делает массив без элементов длины 4, который `join` объединяет в строку, вставляя *между его элементами* строку `"ля"`.
В результате, так как элементы пусты, получается повторение строки. Такой вот небольшой трюк.
[/smart]
````
## Удаление из массива
Так как массивы являются объектами, то для удаления ключа можно воспользоваться обычным `delete`:
```js
//+ run
```js run
var arr = ["Я", "иду", "домой"];
delete arr[1]; // значение с индексом 1 удалено
@ -91,23 +83,20 @@ alert( arr[1] ); // undefined
Поэтому для удаления используются специальные методы: из начала -- `shift`, с конца -- `pop`, а из середины -- `splice`, с которым мы сейчас познакомимся.
## Метод splice
## Метод splice
Метод `splice` -- это универсальный раскладной нож для работы с массивами. Умеет все: удалять элементы, вставлять элементы, заменять элементы -- по очереди и одновременно.
Его синтаксис:
<dl>
<dt>`arr.splice(index[, deleteCount, elem1, ..., elemN])`</dt>
<dd>Удалить `deleteCount` элементов, начиная с номера `index`, а затем вставить `elem1, ..., elemN` на их место. Возвращает массив из удалённых элементов.</dd>
</dl>
`arr.splice(index[, deleteCount, elem1, ..., elemN])`
: Удалить `deleteCount` элементов, начиная с номера `index`, а затем вставить `elem1, ..., elemN` на их место. Возвращает массив из удалённых элементов.
Этот метод проще всего понять, рассмотрев примеры.
Начнём с удаления:
```js
//+ run
```js run
var arr = ["Я", "изучаю", "JavaScript"];
*!*
@ -119,36 +108,33 @@ alert( arr ); // осталось ["Я", "JavaScript"]
В следующем примере мы удалим 3 элемента и вставим другие на их место:
```js
//+ run
```js run
var arr = [*!*"Я", "сейчас", "изучаю",*/!* "JavaScript"];
// удалить 3 первых элемента и добавить другие вместо них
arr.splice(0, 3, "Мы", "изучаем")
arr.splice(0, 3, "Мы", "изучаем")
alert( arr ) // теперь [*!*"Мы", "изучаем"*/!*, "JavaScript"]
```
Здесь видно, что `splice` возвращает массив из удаленных элементов:
```js
//+ run
```js run
var arr = [*!*"Я", "сейчас",*/!* "изучаю", "JavaScript"];
// удалить 2 первых элемента
var removed = arr.splice(0, 2);
// удалить 2 первых элемента
var removed = arr.splice(0, 2);
alert( removed ); // "Я", "сейчас" <-- array of removed elements
```
Метод `splice` также может вставлять элементы без удаления, для этого достаточно установить `deleteCount` в `0`:
```js
//+ run
```js run
var arr = ["Я", "изучаю", "JavaScript"];
// с позиции 2
// удалить 0
// с позиции 2
// удалить 0
// вставить "сложный", "язык"
arr.splice(2, 0, "сложный", "язык");
@ -157,26 +143,24 @@ alert( arr ); // "Я", "изучаю", "сложный", "язык", "JavaScript
Допускается использование отрицательного номера позиции, которая в этом случае отсчитывается с конца:
```js
//+ run
```js run
var arr = [1, 2, 5]
// начиная с позиции индексом -1 (предпоследний элемент)
// удалить 0 элементов,
// удалить 0 элементов,
// затем вставить числа 3 и 4
arr.splice(-1, 0, 3, 4);
alert( arr ); // результат: 1,2,3,4,5
```
## Метод slice
## Метод slice
Метод `slice(begin, end)` копирует участок массива от `begin` до `end`, не включая `end`. Исходный массив при этом не меняется.
Например:
```js
//+ run
```js run
var arr = ["Почему", "надо", "учить", "JavaScript"];
var arr2 = arr.slice(1, 3); // элементы 1, 2 (не включая 3)
@ -185,43 +169,34 @@ alert( arr2 ); // надо, учить
```
Аргументы ведут себя так же, как и в строковом `slice`:
<ul>
<li>Если не указать `end` -- копирование будет до конца массива:
```js
//+ run
var arr = ["Почему", "надо", "учить", "JavaScript"];
- Если не указать `end` -- копирование будет до конца массива:
alert( arr.slice(1) ); // взять все элементы, начиная с номера 1
```
```js run
var arr = ["Почему", "надо", "учить", "JavaScript"];
</li>
<li>Можно использовать отрицательные индексы, они отсчитываются с конца:
alert( arr.slice(1) ); // взять все элементы, начиная с номера 1
```
- Можно использовать отрицательные индексы, они отсчитываются с конца:
```js
var arr2 = arr.slice(-2); // копировать от 2го элемента с конца и дальше
```
```js
var arr2 = arr.slice(-2); // копировать от 2го элемента с конца и дальше
```
- Если вообще не указать аргументов -- скопируется весь массив:
</li>
<li>Если вообще не указать аргументов -- скопируется весь массив:
```js
var fullCopy = arr.slice();
```
```js
var fullCopy = arr.slice();
```
</li>
</ul>
[smart header="Совсем как в строках"]
```smart header="Совсем как в строках"
Синтаксис метода `slice` одинаков для строк и для массивов. Тем проще его запомнить.
[/smart]
```
## Сортировка, метод sort(fn)
## Сортировка, метод sort(fn)
Метод `sort()` сортирует массив *на месте*. Например:
```js
//+ run
```js run
var arr = [ 1, 2, 15 ];
arr.sort();
@ -229,9 +204,9 @@ arr.sort();
alert( arr ); // *!*1, 15, 2*/!*
```
Не заметили ничего странного в этом примере?
Не заметили ничего странного в этом примере?
Порядок стал `1, 15, 2`, это точно не сортировка чисел. Почему?
Порядок стал `1, 15, 2`, это точно не сортировка чисел. Почему?
**Это произошло потому, что по умолчанию `sort` сортирует, преобразуя элементы к строке.**
@ -247,8 +222,7 @@ alert( arr ); // *!*1, 15, 2*/!*
Например, укажем эту функцию явно, отсортируем элементы массива как числа:
```js
//+ run
```js run
function compareNumeric(a, b) {
if (a > b) return 1;
if (a < b) return -1;
@ -273,30 +247,25 @@ arr.sort( compareNumeric*!*()*/!* ); // не сработает
Алгоритм сортировки, встроенный в JavaScript, будет передавать ей для сравнения элементы массива. Она должна возвращать:
<ul>
<li>Положительное значение, если `a > b`,</li>
<li>Отрицательное значение, если `a < b`,</li>
<li>Если равны -- можно `0`, но вообще -- не важно, что возвращать, их взаимный порядок не имеет значения.</li>
</ul>
- Положительное значение, если `a > b`,
- Отрицательное значение, если `a < b`,
- Если равны -- можно `0`, но вообще -- не важно, что возвращать, их взаимный порядок не имеет значения.
[smart header="Алгоритм сортировки"]
````smart header="Алгоритм сортировки"
В методе `sort`, внутри самого интерпретатора JavaScript, реализован универсальный алгоритм сортировки. Как правило, это ["\"быстрая сортировка\""](http://algolist.manual.ru/sort/quick_sort.php), дополнительно оптимизированная для небольших массивов.
Он решает, какие пары элементов и когда сравнивать, чтобы отсортировать побыстрее. Мы даём ему функцию -- способ сравнения, дальше он вызывает её сам.
Кстати, те значения, с которыми `sort` вызывает функцию сравнения, можно увидеть, если вставить в неё `alert`:
```js
//+ run
```js run
[1, -2, 15, 2, 0, 8].sort(function(a, b) {
alert( a + " <> " + b );
});
```
````
[/smart]
[smart header="Сравнение `compareNumeric` в одну строку"]
````smart header="Сравнение `compareNumeric` в одну строку"
Функцию `compareNumeric` для сравнения элементов-чисел можно упростить до одной строчки.
```js
@ -305,16 +274,14 @@ function compareNumeric(a, b) {
}
```
Эта функция вполне подходит для `sort`, так как возвращает положительное число, если `a > b`, отрицательное, если наоборот, и `0`, если числа равны.
[/smart]
Эта функция вполне подходит для `sort`, так как возвращает положительное число, если `a > b`, отрицательное, если наоборот, и `0`, если числа равны.
````
## reverse
Метод [arr.reverse()](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reverse) меняет порядок элементов в массиве на обратный.
```js
//+ run
```js run
var arr = [1, 2, 3];
arr.reverse();
@ -327,8 +294,7 @@ alert( arr ); // 3,2,1
Например:
```js
//+ run
```js run
var arr = [1, 2];
*!*
var newArr = arr.concat(3, 4);
@ -343,8 +309,7 @@ alert( newArr ); // 1,2,3,4
Например:
```js
//+ run
```js run
var arr = [1, 2];
*!*
@ -358,17 +323,15 @@ alert( newArr ); // 1,2,3,4,5
Эти методы не поддерживаются в IE8-. Для их поддержки подключите библиотеку [ES5-shim](https://github.com/kriskowal/es5-shim).
Метод ["arr.indexOf(searchElement[, fromIndex])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf) возвращает номер элемента `searchElement` в массиве `arr` или `-1`, если его нет.
Метод ["arr.indexOf(searchElement[, fromIndex])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf) возвращает номер элемента `searchElement` в массиве `arr` или `-1`, если его нет.
Поиск начинается с номера `fromIndex`, если он указан. Если нет -- с начала массива.
**Для поиска используется строгое сравнение `===`.**
**Для поиска используется строгое сравнение `===`.**
Например:
```js
//+ run
```js run
var arr = [1, 0, false];
alert( arr.indexOf(0) ); // 1
@ -378,13 +341,13 @@ alert( arr.indexOf(null) ); // -1
Как вы могли заметить, по синтаксису он полностью аналогичен методу [indexOf для строк](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/indexOf).
Метод ["arr.lastIndexOf(searchElement[, fromIndex])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf) ищет справа-налево: с конца массива или с номера `fromIndex`, если он указан.
Метод ["arr.lastIndexOf(searchElement[, fromIndex])"](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf) ищет справа-налево: с конца массива или с номера `fromIndex`, если он указан.
[warn header="Методы `indexOf/lastIndexOf` осуществляют поиск перебором"]
```warn header="Методы `indexOf/lastIndexOf` осуществляют поиск перебором"
Если нужно проверить, существует ли значение в массиве -- его нужно перебрать. Только так. Внутренняя реализация `indexOf/lastIndexOf` осуществляет полный перебор, аналогичный циклу `for` по массиву. Чем длиннее массив, тем дольше он будет работать.
[/warn]
```
[smart header="Коллекция уникальных элементов"]
````smart header="Коллекция уникальных элементов"
Рассмотрим задачу -- есть коллекция строк, и нужно быстро проверять: есть ли в ней какой-то элемент. Массив для этого не подходит из-за медленного `indexOf`. Но подходит объект! Доступ к свойству объекта осуществляется очень быстро, так что можно сделать все элементы ключами объекта и проверять, есть ли уже такой ключ.
Например, организуем такую проверку для коллекции строк `"div"`, `"a"` и `"form"`:
@ -400,13 +363,10 @@ for (var i = 0; i < items.length; i++) {
}
```
Теперь для проверки, есть ли ключ `key`, достаточно выполнить `if (store[key])`. Если есть -- можно использовать значение, если нет -- добавить.
Теперь для проверки, есть ли ключ `key`, достаточно выполнить `if (store[key])`. Если есть -- можно использовать значение, если нет -- добавить.
Такое решение работает только со строками, но применимо к любым элементам, для которых можно вычислить строковый "уникальный ключ".
[/smart]
````
## Object.keys(obj)
@ -414,8 +374,7 @@ for (var i = 0; i < items.length; i++) {
Если мы хотим работать с ними в виде массива, то к нашим услугам -- замечательный метод [Object.keys(obj)](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys). Он поддерживается везде, кроме IE8-:
```js
//+ run
```js run
var user = {
name: "Петя",
age: 30
@ -429,13 +388,12 @@ alert( keys ); // name, age
## Итого
Методы:
<ul>
<li>`push/pop`, `shift/unshift`, `splice` -- для добавления и удаления элементов.</li>
<li>`join/split` -- для преобразования строки в массив и обратно.</li>
<li>`sort` -- для сортировки массива. Если не передать функцию сравнения -- сортирует элементы как строки.</li>
<li>`reverse` -- меняет порядок элементов на обратный.</li>
<li>`concat` -- объединяет массивы.</li>
<li>`indexOf/lastIndexOf` -- возвращают позицию элемента в массиве (не поддерживается в IE8-).</li>
</ul>
- `push/pop`, `shift/unshift`, `splice` -- для добавления и удаления элементов.
- `join/split` -- для преобразования строки в массив и обратно.
- `sort` -- для сортировки массива. Если не передать функцию сравнения -- сортирует элементы как строки.
- `reverse` -- меняет порядок элементов на обратный.
- `concat` -- объединяет массивы.
- `indexOf/lastIndexOf` -- возвращают позицию элемента в массиве (не поддерживается в IE8-).
Изученных нами методов достаточно в 95% случаях, но существуют и другие. Для знакомства с ними рекомендуется заглянуть в справочник <a href="http://javascript.ru/Array">Array</a> и [Array в Mozilla Developer Network](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array).