Работа с массивами в javascript
Содержание:
- Array.isArray
- Область видимости
- Пример использования
- Добавление или удаление элементов массива в любой позиции
- Инициализация массива в JavaScript
- Ассоциативный массив — что это?
- JavaScript массивы, тип данных Array
- Б. Перебор массивоподобных объектов
- Объект Map (ассоциативный массив)
- Значения параметров
- Обработка элементов массива
- Symbol.iterator
- Объявление
- А. Перебор настоящих массивов
- Копирование массива в JavaScript
- Итого
Array.isArray
Массивы не
образуют отдельный тип языка. Они основаны на объектах. Поэтому typeof не может
отличить простой объект от массива:
console.log(typeof {}); // object console.log (typeof ); // тоже object
Но массивы
используются настолько часто, что для этого придумали специальный метод: Array.isArray(value). Он возвращает
true, если value массив, и false, если нет.
console.log(Array.isArray({})); // false console.log(Array.isArray()); // true
Подведем итоги
по рассмотренным методам массивов. У нас получился следующий список:
Для |
|
push(…items) |
добавляет элементы в конец |
pop() |
извлекает элемент с конца |
shift() |
извлекает элемент с начала |
unshift(…items) |
добавляет элементы в начало |
splice(pos, deleteCount, …items) |
начиная с индекса pos, удаляет |
slice(start, end) |
создаёт новый массив, копируя в него |
concat(…items) |
возвращает новый массив: копирует все |
Для поиска |
|
indexOf/lastIndexOf(item, pos) |
ищет item, начиная с позиции pos, и |
includes(value) |
возвращает true, если в массиве |
find/filter(func) |
фильтрует элементы через функцию и |
findIndex(func) |
похож на find, но возвращает индекс |
Для перебора |
|
forEach(func) |
вызывает func для каждого элемента. |
Для |
|
map(func) |
создаёт новый массив из результатов |
sort(func) |
сортирует массив «на месте», а потом |
reverse() |
«на месте» меняет порядок следования |
split/join |
преобразует строку в массив и обратно |
reduce(func, initial) |
вычисляет одно значение на основе |
Видео по теме
JavaScipt #1: что это такое, с чего начать, как внедрять и запускать
JavaScipt #2: способы объявления переменных и констант в стандарте ES6+
JavaScript #3: примитивные типы number, string, Infinity, NaN, boolean, null, undefined, Symbol
JavaScript #4: приведение типов, оператор присваивания, функции alert, prompt, confirm
JavaScript #5: арифметические операции: +, -, *, /, **, %, ++, —
JavaScript #6: условные операторы if и switch, сравнение строк, строгое сравнение
JavaScript #7: операторы циклов for, while, do while, операторы break и continue
JavaScript #8: объявление функций по Function Declaration, аргументы по умолчанию
JavaScript #9: функции по Function Expression, анонимные функции, callback-функции
JavaScript #10: анонимные и стрелочные функции, функциональное выражение
JavaScript #11: объекты, цикл for in
JavaScript #12: методы объектов, ключевое слово this
JavaScript #13: клонирование объектов, функции конструкторы
JavaScript #14: массивы (array), методы push, pop, shift, unshift, многомерные массивы
JavaScript #15: методы массивов: splice, slice, indexOf, find, filter, forEach, sort, split, join
JavaScript #16: числовые методы toString, floor, ceil, round, random, parseInt и другие
JavaScript #17: методы строк — length, toLowerCase, indexOf, includes, startsWith, slice, substring
JavaScript #18: коллекции Map и Set
JavaScript #19: деструктурирующее присваивание
JavaScript #20: рекурсивные функции, остаточные аргументы, оператор расширения
JavaScript #21: замыкания, лексическое окружение, вложенные функции
JavaScript #22: свойства name, length и методы call, apply, bind функций
JavaScript #23: создание функций (new Function), функции setTimeout, setInterval и clearInterval
Область видимости
Директива при объявлении переменной делает ее локальной, то есть видимой только внутри текущей функции. Все остальные переменные являются глобальными.
Локальная переменная объявляется так:
var i
При объявлении можно тут же присвоить переменной значение и объявить другие переменные:
// то же самое что 3 отдельных объявления c var var a=5, b=6, str = "Строка"
В следующем примере переменная в функции объявлена как локальная. Поэтому глобальное значение не изменяется в процессе выполнения .
a = 1 function go() { var a = 6 } go() alert(a) // => 1
А здесь — ключевое слово опущено, поэтому значение меняется:
a = 1 function go() { a = 6 } go() alert(a) // => 6
Кстати, глобальных переменных в javascript на самом деле нет. То, что называют «глобальными» — на самом деле свойства специального объекта window. Например, в последнем примере тоже выдало бы .
Все «глобальные» переменные привязаны к своему окну. Разные окна и фреймы имеют разные «глобальные» переменные, которыми могут обмениваться друг с другом.
Вообще, глобальных переменных в JS рекомендуется избегать, особенно при написании библиотек и компонент, которые предполагается использовать в разных приложениях.
Как правило — всё, что относится к компоненту, объявляется в виде свойств единого глобального объекта: ExtJS, dojo и т.п. Вы можете увидеть это в любом известном JS-фреймворке.
Обратите внимание, в javascript все директивы var срабатывают при входе в функцию, неважно где они находятся. Например, посмотрим на функцию:
Например, посмотрим на функцию:
function cmp(a,b) { if (a>b) { res = 1 } else if (a<b) { res = -1 } else { var res = 0 } return res }
При входе в функцию интерпретатор javascript находит все объявления и создает соответствующие локальные переменные.
Поэтому в примере выше переменная будет во всех случаях локальная. Несмотря на то, что само объявление находится ниже по коду, чем первое обращение к , интерпретатор создает все переменные на этапе входа в функцию, так что эта переменная локальна.
Пример использования
В следующем примере мы рассмотрим как получить сумму всех элементов массива с использованием JavaScript метода forEach():
var array = ; // инициализируем переменную, содержащую массив числовых значений var sum = ; // инициализируем переменную, содержащую числовое значение array.forEach( // перебираем все элементы массива array function sumNumber( currentValue ) { sum += currentValue; } ); console.log( sum ); // выводим значение переменной sum равное 50
В следующем примере мы рассмотрим использование второго аргумента метода forEach(), который указывает на объект, на который мы можем ссылаться с использованием ключевого слова this внутри функции обратного вызова:
var numbers = ; // инициализируем переменную, содержащую массив числовых значений var squared = []; // инициализируем переменную, содержащую пустой массив var myObject = { // инициализируем переменную, содержащую объект square: function( currentValue ) { // метод объекта, который принимает значение return currentValue * currentValue; // и возвращает его возведенным в квадрат } }; numbers.forEach( // перебираем все элементы массива numbers function( currentValue ) { squared.push( this.square( currentValue ) ); // добавляем в массив squared возвращаемое значение метода square объекта myObject }, myObject // объект, на который мы ссылаемся с использованием ключевого слова this ); console.log( squared ); // выводим значение переменной squared равное ;
JavaScript Array
Добавление или удаление элементов массива в любой позиции
Метод splice() — это очень универсальный метод массива, который позволяет добавлять или удалять элементы любого индекса, используя синтаксис arr.splice(startIndex, deleteCount, elem1, …, elemN).
Этот метод принимает три параметра: первый параметр — это индекс, с которого начинается объединение массива (обязателен); второй параметр — количество удаляемых элементов (используйте 0, если вы не хотите удалять какие-либо элементы) (параметр необязательный), и третий параметр представляет собой набор заменяющих элементов, он также является необязательным. В следующем примере показано, как это работает:
var colors = ; var removed = colors.splice(0,1); // Удалить первый элемент document.write(colors); // Результат: Green,Blue document.write(removed); // Результат: Red (массив из одного элемента) document.write(removed.length); // Результат: 1 removed = colors.splice(1, 0, "Pink", "Yellow"); // Вставить два элемента начиная с позиции 1 document.write(colors); // Результат: Green,Pink,Yellow,Blue document.write(removed); // Пустой массив document.write(removed.length); // Результат: 0 removed = colors.splice(1, 1, "Purple", "Voilet"); // Вставить два элемента, удалить один document.write(colors); // Результат: Green,Purple,Voilet,Yellow,Blue document.write(removed); // Результат: Pink (массив из одного элемента) document.write(removed.length); // Результат: 1
Метод splice() возвращает массив удаленных элементов или пустой массив, если элементы не были удалены, как вы можете видеть в приведенном выше примере. Если второй аргумент опущен, все элементы от начала до конца массива удаляются. В отличие от методов slice() и concat(), метод splice() модифицирует массив, для которого он вызывается.
Инициализация массива в JavaScript
В JavaScript мы можем создать пустой массив, применяя для этого квадратные скобки либо конструктор Array:
var users = new Array(); var people = []; console.log(users); // Array console.log(people); // Array
Кроме того, мы можем сразу же инициализировать наш массив некоторым числом элементов:
var users = new Array("Bill", "Tom", "Alice"); var people = "Sam", "John", "Kate"]; console.log(users); // console.log(people); //
Также можем определить массив, по ходу определяя в него новые элементы:
var users = new Array(); users1 = "Tom"; users2 = "Kate"; console.log(users1]); // "Tom" console.log(users]); // undefined
Обратите внимание, что не имеет значения, что массив по умолчанию создаётся с нулевой длиной. Используя индексы, мы сможем подставить тот или иной элемент на конкретный индекс в массиве
length
Если хотим узнать длину массива в JS, используем свойство length:
var fruit = new Array(); fruit = "груши"; fruit1 = "яблоки"; fruit2 = "сливы"; document.write("В массиве fruit " + fruit.length + " элемента: <br/>"); for(var i=; i < fruit.length; i++) document.write(fruiti + "<br/>");
Фактически, длиной нашего массива в JavaScript будет индекс последнего элемента, плюс единица. К примеру:
var users = new Array(); // в массиве 0 элементов users = "Kate"; users1 = "Tom"; users4 = "Sam"; for(var i=; i<users.length;i++) console.log(usersi]);
В этом случае вывод браузера будет следующим:
Kate Tom undefined undefined Sam
Вне зависимости от того, что для индексов №№ 2 и 3 мы элементов не добавляли, длиной массива будет число 5, ведь элементы с индексами №№ 2 и 3 будут просто иметь значение undefined.
Ассоциативный массив — что это?
Под ассоциативным массивом подразумевают массив, в котором в качестве ключей применяются строки. То есть речь идёт о совокупности пар «ключ-значение». Таким образом, в ассоциативном массиве любое значение связано с конкретным ключом, а доступ к этому значению производится по имени ключа.
Мы можем представить ассоциативный массив в виде небольшого ящика, где находятся отделения. Каждое отделение имеет имя (это ключ) и содержимое (это значение). Естественно, чтобы найти нужное отделение в ящике, мы должны знать имя отделения (ключ). Зная это имя, мы сможем получить содержимое отделения (значение).
JavaScript массивы, тип данных Array
Теперь подробнее рассмотрим объект массив.
Массив — упорядоченный набор данных.
Доступ к элементам массива осуществляется с помощью порядкового номера — индекса. Таким образом, массив — объект, представляющий собой проиндексированный набор элементов.
Пример: Создать массив arr. Присвоить значение трем элементам созданного массива. С помощью диалогового окна вывести значение элемента массива с индексом 2. Вывести количество элементов массива.
Решение:
1 2 3 4 5 6 |
var arr = new Array(); arr = "element1"; arr1 = "element2"; arr2 = "element3"; alert(arr2); alert("Число элементов" + arr.length); |
В javascript длина массива — свойство .
Б. Перебор массивоподобных объектов
В JavaScript есть не только настоящие массивы, но и массивоподобные объекты. У них есть свойство length и свойства с именами в виде чисел, которые соответствуют элементам массива. Это DOM-коллекции NodeList либо псевдомассив arguments, доступный внутри любого метода/функции.
1. Применяем способы перебора настоящих массивов
Практически все способы перебора настоящих массивов можно применять для перебора массивоподобных объектов. Например, при использовании конструкций for и for…in всё делается тем же путём.
Что касается forEach и прочих методов Array.prototype, то тут надо использовать вызов Function.apply.или Function.call.
Допустим, вы желаете применить forEach к свойству childNodes объекта Node:
Array.prototype.forEach.call(node.childNodes, function(child) { // делаем что-либо с объектом child });
Чтобы было удобнее повторно использовать этот приём, объявите ссылку на метод Array.prototype.forEach в отдельной переменной и используйте её как сокращение:
// (Считаем, что весь код ниже находится в одной области видимости) var forEach = Array.prototype.forEach; // ... forEach.call(node.childNodes, function(child) { // делаем что-либо с объектом child });
Когда в массивоподобном объекте есть итератор, его можно задействовать явно либо неявно для перебора объекта тем же способом, как и в случае с настоящими массивами.
2. Преобразование массивоподобного объекта в настоящий массив
Простой способ перебора — преобразовать массивоподобный объект в настоящий массив. Для этого подходит, универсальный метод Array.prototype.slice:
var trueArray = Array.prototype.slice.call(arrayLikeObject, );
Если же желаете преобразовать коллекцию NodeList в настоящий массив, то лучше действовать несколько иначе:
var divs = Array.prototype.slice.call(document.querySelectorAll("div"), );
Кроме того, вместо Array.prototype.slice можно использовать и Array.from.
На этом всё, удачного вам кодинга!
Объект Map (ассоциативный массив)
Тип данных предназначен для создания ассоциативных массив (пар «ключ-значение»). В качестве ключа можно использовать как примитивные, так и ссылочные типы данных. Это одно из основных отличий от ассоциативных массивов как объектов, у которых в качестве ключа можно использовать только строки.
Пример создание ассоциативного массива (экземпляра объекта Map):
// создание пустого ассоциативного массива var arr1 = new Map(); // создание ассоциативного массива и добавление в него 3 пары "ключ-значение" var arr = new Map(, , ]);
Узнать количество элементов в массиве можно осуществить с помощью свойства :
arr.size; // 3
Добавление элемента в массив (в экземпляр объекта Map) осуществляется с помощью метода :
// добавить в массив одну пару "ключ-значение" arr.set('key4','value4'); // добавить в массив несколько пар "ключ-значение" arr.set('key5','value5'); arr.set('key6','value6'); // или так arr .set('key5','value5') .set('key6','value6');
Если в массиве есть уже такой ключ, то произойдёт установка нового значения, которое будет связано с ним:
arr.set('key1','new value');
Получить значение по ключу выполняется с помощью метода :
// получить значение, ассоциированное с ключом 'key4' arr.get('key4'); // 'value4'
Проверить есть ли ключ в массиве можно посредством метода :
// есть ли в массиве arr ключ key2 arr.has('key2'); // true
Удалить из ассоциативного массива (экземпляра объекта Map) элемент по имени ключа можно с помощью метода :
arr.delete('key1'); // true
Данный метод возвращает , если данный ключ существовал в массиве, в противном случае он возвращает .
if (arr.delete('key1')) { console.log('Запись с ключом "key1" удалена из массива!'); } else { console.log('Запись с ключом "key1" не найдена в массиве!'); }
Очистить массив (удалить все элементы) можно выполнить с помощью метода .
arr.clear(); // очистим массив arr arr.size; // 0 (количество элементов)
Перебор ассоциативного массива (объекта Map) обычно осуществляется с помощью цикла . При этом итерацию можно организовать по ключам, значениям и записям ().
Перебор ключей можно осуществить посредством итерируемого объекта , возвращаемым методом :
for (let key of arr.keys()) { console.log(key); }
Для перебора значений можно воспользоваться итерируемым объектом , возвращаемым посредством методом :
for (let value of arr.values()) { console.log(value); }
Перебор записей ассоциативного массива с использованием метода :
for (let pair of arr.entries()) { // pair - это массив console.log(pair); // ключ console.log(pair); // значение console.log(`Ключ = ${pair}, значение = ${pair}`); }
Данный метод используется по умолчанию в for…of, поэтому его можно опустить:
for (let pair of arr) { console.log(`Ключ = ${pair}, значение = ${pair}`); }
Кроме этого перебрать ассоциативный массив можно с помощью метода forEach.
arr.forEach(function(value,key) { console.log('key = ' + key +', value = ' + value); });
Преобразовать ассоциативный массив (объект Map) в JSON и обратно можно так:
let arr = new Map(, , , ]); // в JSON jsonStr = JSON.stringify(); // из JSON в Map mapArr = new Map(JSON.parse(jsonStr));
Значения параметров
Параметр | Описание |
---|---|
function | Функция обратного вызова, которая будет выполнена один раз для каждого элемента в массиве. Функция принимает следующие параметры:
Если в качестве параметра метода передается что-то, что не является объектом функции, то будет вызвано исключение TypeError. Обязательный параметр. |
thisValue | Объект, на который может ссылаться ключевое слово this внутри функции обратного вызова. Если параметр thisValue не используется, то в качестве значения this будет использоваться undefined (в конечном счете this будет зависеть от обычных правил контекста выполнения функции). Необязательный параметр. |
Обработка элементов массива
Существует несколько стандартных алгоритмов
обработки элементов массива:
-
Удаление значения из массива по
определенному индексу. -
Вставка значения в массив по
определенному индексу. - Сортировка элементов массива.
Начнем с первого
– удаления элемента из массива. Создадим вот такой массив:
final int N = 9; short a = new shortN;
запишем туда
значения с 1 по 9:
for(int i=;i < N;++i) ai = (short)(i+1);
Теперь удалим
элемент со значением 6. Для этого нужно проделать такую операцию:
Причем, сначала
перемещаем 7-ку на место 6-ку, затем 8-ку и 9-ку, то есть, двигаемся от
удаляемого элемента к концу массива. Программа будет выглядеть так:
final int N = 9; short a = new shortN; for(int i=;i < N;++i) ai = (short)(i+1); for (int i = 5; i < N-1; ++i) ai = ai + 1; for (short val a) System.out.print(val+" ");
Здесь мы начали
движение с 5-го индекса (то есть 6-го элемента массива) и на первой итерации
делаем операцию a=a, то есть, 7-ку ставим на место 6-ки.
На следующей итерации уже имеем a=a – перемещаем
8-ку и, затем, a=a – перемещаем 9-ку. Все, в итоге
значение 6 было удалено из массива.
Теперь реализуем второй алгоритм и
вставим значение 4, которого не хватает вот в таком массиве:
short a = new short {1, 2, 3, 5, 6, 7, 8, 9, 9};
Здесь в конце записаны две 9, чтобы мы
могли сдвинуть все элементы на 1 вправо и вставить элемент со значением 4. То
есть, нам следует выполнить такую операцию над элементами массива:
Обратите
внимание, что сдвиг осуществляется с конца массива. Если мы начнем это делать с
4-го, то просто затрем все остальные значения пятеркой
Итак, вот программа,
которая вставляет 4-ку в этот массив:
short a = new short {1, 2, 3, 5, 6, 7, 8, 9, 9}; for (int i = 8; i > 3; --i) ai = ai - 1; a3 = 4; for (short val a) System.out.print(val+" ");
Здесь счетчик i в цикле сначала
равен 8 – это индекс последнего элемента нашего массива. Затем, делается
операция a=a, то есть, a=a. Таким
образом, мы присваиваем 8-му элементу значение 7-го элемента. Это и есть
смещение значения вправо. На следующей итерации i уменьшается на
1, то есть, равно 7 и операция повторяется: a=a и так далее,
последний смещаемый элемент будет: a=a. После этого
i будет равно 3,
условие цикла становится ложным и он завершается. После смещения, мы
присваиваем 4-му элементу массива значение 4 и выводим получившийся массив на
экран.
Теперь
рассмотрим довольно распространенный алгоритм сортировки элементов массива по
методу всплывающего пузырька. Реализуем его на языке Java.
byte a = {3, 5, 1, 6, 2, 4}; for (int i = ; i < a.length-1; ++i) { byte min = ai; int pos = i; for (int j = i + 1; j < a.length; ++j) if (min > aj) { pos = j; min = aj; } byte t = ai; ai = apos; apos = t; } for (short val a) System.out.print(val+" ");
Здесь первый
цикл показывает с какого элемента искать минимальный, то есть, это
местоположение той вертикальной черты в методе всплывающего пузырька. Затем,
задаем две вспомогательные переменные min – минимальное найденное
значение, pos – индекс
минимального элемента в массиве. Второй вложенный цикл перебирает все
последующие элементы массива и сравнивает его с текущим минимальным и если
будет найдено меньшее значение, то min становится
равной ему и запоминается его позиция. Вот эти три строчки меняют местами
текущее значение элемента с найденным минимальным, используя вспомогательную
переменную t. И в конце
программы выполняется вывод элементов массива на экран.
Запустим эту
программу и посмотрим как она работает. Кстати, если мы теперь хотим выполнить
сортировку по убыванию, то достаточно изменить вот этот знак на
противоположный.
Видео по теме
#1 Установка пакетов и первый запуск программы
#2 Структура программы, переменные, константы, оператор присваивания
#3 Консольный ввод/вывод, импорт пакетов
#4 Арифметические операции
#5 Условные операторы if и switch
#6 Операторы циклов while, for, do while
#7 Массивы, обработка элементов массива
#8 (часть 1) Строки в Java, методы класса String
#8 (часть 2) Строки — классы StringBuffer и StringBuider
#9 Битовые операции И, ИЛИ, НЕ, XOR
#10 Методы, их перегрузка и рекурсия
Symbol.iterator
Мы легко поймём принцип устройства перебираемых объектов, создав один из них.
Например, у нас есть объект. Это не массив, но он выглядит подходящим для .
Например, объект , который представляет собой диапазон чисел:
Чтобы сделать итерируемым (и позволить работать с ним), нам нужно добавить в объект метод с именем (специальный встроенный , созданный как раз для этого).
- Когда цикл запускается, он вызывает этот метод один раз (или выдаёт ошибку, если метод не найден). Этот метод должен вернуть итератор – объект с методом .
- Дальше работает только с этим возвращённым объектом.
- Когда хочет получить следующее значение, он вызывает метод этого объекта.
- Результат вызова должен иметь вид , где означает, что итерация закончена, в противном случае содержит очередное значение.
Вот полная реализация с пояснениями:
Обратите внимание на ключевую особенность итераторов: разделение ответственности
- У самого нет метода .
- Вместо этого другой объект, так называемый «итератор», создаётся вызовом , и именно его генерирует значения.
Таким образом, итератор отделён от самого итерируемого объекта.
Технически мы можем объединить их и использовать сам как итератор, чтобы упростить код.
Например, вот так:
Теперь возвращает сам объект : у него есть необходимый метод , и он запоминает текущее состояние итерации в . Короче? Да. И иногда такой способ тоже хорош.
Недостаток такого подхода в том, что теперь мы не можем использовать этот объект в двух параллельных циклах : у них будет общее текущее состояние итерации, потому что теперь существует лишь один итератор – сам объект. Но необходимость в двух циклах , выполняемых одновременно, возникает редко, даже при наличии асинхронных операций.
Бесконечные итераторы
Можно сделать бесконечный итератор. Например, будет бесконечным при . Или мы можем создать итерируемый объект, который генерирует бесконечную последовательность псевдослучайных чисел. Это бывает полезно.
Метод не имеет ограничений, он может возвращать всё новые и новые значения, это нормально.
Конечно же, цикл с таким итерируемым объектом будет бесконечным. Но мы всегда можем прервать его, используя .
Объявление
Существует два варианта синтаксиса для создания пустого массива:
Практически всегда используется второй вариант синтаксиса. В скобках мы можем указать начальные значения элементов:
Элементы массива нумеруются, начиная с нуля.
Мы можем получить элемент, указав его номер в квадратных скобках:
Мы можем заменить элемент:
…Или добавить новый к существующему массиву:
Общее число элементов массива содержится в его свойстве :
Вывести массив целиком можно при помощи .
В массиве могут храниться элементы любого типа.
Например:
Висячая запятая
Список элементов массива, как и список свойств объекта, может оканчиваться запятой:
«Висячая запятая» упрощает процесс добавления/удаления элементов, так как все строки становятся идентичными.
А. Перебор настоящих массивов
Для этого используются:
1. Известный метод Array.prototype.forEach.
2. Классический цикл for.
3. «Правильно» построенный цикл for…in.
Что же, давайте рассмотрим эти методы подробнее.
1. Метод forEach
Пример использования:
var a = "a", "b", "c"]; a.forEach(function(entry) { console.log(entry); });
Достоинства forEach заключаются в том, что вам не надо объявлять локальные переменные, чтобы хранить индекс и значения текущего элемента массива, так как они автоматически передаются в функцию обратного вызова (так называемый колбэк) в качестве аргументов.
С помощью forEach вы не только сможете выполнить перебор всех элементов массива, но и получите возможность выполнения некоторых действий с массивами:
1) some — возвращает true, когда хотя бы для одного элемента массива колбэк возвращает значение, приводимое к true;
2) every — возвращает true, когда для каждого элемента массива колбэк возвращает значение, приводимое к true;
3) filter — обеспечивает создание нового массива, включающего те элементы исходного, для коих колбэк возвращает true;
4) reduce — сводит массив к единственному значению, т. е. колбэк применяется по очереди к каждому элементу массива, начиная с 1-го (полезно при вычислении суммы элементов массива и прочих итоговых функций);
5) map — обеспечивает создание нового массива, состоящего из значений, которые возвращаются колбэком;
6) reduceRight — работает так же, как и reduce с той лишь разницей, что перебирает элементы в обратном порядке.
2. Цикл for
Что тут скажешь — старый добрый for…
var a = "a", "b", "c"]; var index; for (index = ; index < a.length; ++index) { console.log(aindex]); }
Кстати, когда длина массива неизменна в течение цикла, а цикл принадлежит критическому с точки зрения производительности участку кода (что маловероятно), подходит «более оптимальная» версия for с хранением длины массива:
var a = "a", "b", "c"]; var index, len; for (index = , len = a.length; index < len; ++index) { console.log(aindex]); }
По идее, данный код должен выполняться немного быстрее предыдущего.
Если же порядок перебора элементов не особо важен, можно выполнить очередную оптимизацию, избавившись от переменной хранения длины массива и изменив прямой порядок перебора на обратный:
var a = "a", "b", "c"]; var index; for (index = a.length - 1; index >= ; --index) { console.log(aindex]); }
Однако справедливости ради стоит отметить, что в современных движках JavaScript вышеописанные игры с оптимизацией мало что значат.
3. Правильное использование цикла for…in
Вообще, цикл for…in не предназначен для перебора массивов. Он перебирает не индексы нашего массива, а перечисляемые свойства объекта.
Однако, если нам нужен перебор разреженных массивов, цикл for…in может быть весьма полезным, если, разумеется, соблюдать меры предосторожности:
// a — разреженный массив var a = []; a = "a"; a10 = "b"; a10000 = "c"; for (var key in a) { if (a.hasOwnProperty(key) && /^0$|^\d*$/.test(key) && key <= 4294967294) { console.log(akey]); } }
В вышеописанном примере на каждой циклической итерации осуществляются 2 проверки:
1) то, что массив имеет своё свойство с именем key (ненаследованное из его прототипа);
2) то, что key — это строка, содержащая десятичную запись целого числа, значение которого менее 4294967294.
Да, такие проверки могут отнять много времени, но если мы имеем дело с разреженным массивом, данный способ эффективнее обычного цикла for, т. к. в последнем случае перебираются лишь элементы, которые определены в массиве явно. Например в коде выше произойдёт всего 3 итерации (для индексов 0, 10 и 10000), в то время как при использовании классического for — 10001 итерация.
Кстати, код проверок можете оформить в виде отдельной функции:
function arrayHasOwnIndex(array, key) { return array.hasOwnProperty(key) && /^0$|^\d*$/.test(key) && key <= 4294967294; }
В таком случае тело цикла существенно сократится:
for (key in a) { if (arrayHasOwnIndex(a, key)) { console.log(akey]); } }
Вышеописанный код универсален, но вы можете использовать версию и короче. Формально она не совсем правильна, зато подходит практически для любых случаев:
for (key in a) { if (a.hasOwnProperty(key) && String(parseInt(key, 10)) === key) { console.log(akey]); } }
Копирование массива в JavaScript
slice()
В JS копирование массива бывает поверхностным либо неглубоким (shallow copy) а также deep copy, то есть глубоким.
В первом случае мы присваиваем переменной значение другой переменной, хранящей массив:
var users = "Tom", "Bob", "Bill"]; console.log(users); // var people = users; // shallow copy people1 = "John"; // меняем 2-й элемент console.log(users); //
В нашем случае переменная people после неглубокого копирования станет указывать на тот же массив, что и переменная users. Именно поэтому в случае изменения элементов в people, поменяются элементы и в users, ведь по факту это один и тот же массив.
Вышеописанное поведение не всегда желательно. К примеру, нам надо, чтобы после копирования переменные указывали на отдельные массивы. Тогда подойдёт глубокое копирование посредством метода slice():
var users = "Tom", "Bob", "Bill"]; console.log(users); // var people = users.slice(); // deep copy people1 = "John"; // меняем 2-й элемент console.log(users); // console.log(people); //
Теперь после копирования переменные станут указывать на разные массивы, поэтому мы сможем менять их отдельно друг от друга.
Кроме того, функция slice() даёт возможность копировать часть массива:
var users = "Tom", "Bob", "Bill", "Alice", "Kate"]; var people = users.slice(1, 4); console.log(people); //
В функцию slice() мы передаём начальный и конечный индексы, используемые для выборки значений из нашего массива. В таком случае выборка в новый массив начнётся с первого индекса по индекс № 4, не включая его. И, так как индексация массивов в JavaScript начинается с нуля, в новом массиве будут 2-й, 3-й и 4-й элементы.
push()
Функция push() добавит элемент в конец нашего массива:
var fruit = []; fruit.push("груши"); fruit.push("яблоки"); fruit.push("сливы"); fruit.push("вишни","абрикосы"); document.write("В массиве fruit " + fruit.length + " элемента: <br/>"); document.write(fruit); // груши,яблоки,сливы,вишни,абрикосы
pop()
Такая функция, как pop(), удалит последний элемент из JavaScript-массива:
var fruit = "груши", "яблоки", "сливы"]; var lastFruit = fruit.pop(); // из массива извлекается последний элемент document.write(lastFruit + "<br/>"); document.write("В массиве fruit " + fruit.length + " элемента: <br/>"); for(var i=; i <fruit.length; i++) document.write(fruiti + "<br/>");
Итоговый вывод:
сливы В массиве fruit 2 элемента: груши яблоки
shift()
Теперь рассмотрим функцию shift(). Она может извлекать и удалять 1-й элемент из массива:
var fruit = "груши", "яблоки", "сливы"]; var firstFruit = fruit.shift(); document.write(firstFruit + "<br/>"); document.write("В массиве fruit " + fruit.length + " элемента: <br/>"); for(var i=; i <fruit.length; i++) document.write(fruiti + "<br/>");
Вывод следующий:
груши В массиве fruit 2 элемента: яблоки сливы
unshift()
Что касается функции unshift(), то она добавит новый элемент в самое начало массива:
var fruit = "груши", "яблоки", "сливы"]; fruit.unshift("апельсины"); document.write(fruit);
Вывод браузера:
апельсины,груши,яблоки,сливы
Итого
- В логическом контексте объект – всегда .
- При строковом преобразовании объекта используется его метод . Он должен возвращать примитивное значение, причём не обязательно именно строку.
- Для численного преобразования используется метод , который также может возвратить любое примитивное значение. У большинства объектов не работает (возвращает сам объект и потому игнорируется), при этом для численного преобразования используется .
Полный алгоритм преобразований есть в спецификации ECMAScript, смотрите пункты , , а также и .
Заметим, для полноты картины, что некоторые тесты знаний в интернет предлагают вопросы типа:
Если вы запустите эти выражения в консоли, то результат может показаться странным. Подвох здесь в том, что если фигурные скобки идут не в выражении, а в основном потоке кода, то JavaScript считает, что это не объект, а «блок кода» (как , , но без оператора просто группировка команд вместе используется редко).
Вот блок кода с командой:
А если команду изъять, то будет пустой блок , который ничего не делает. Два примера выше как раз содержат пустой блок в начале, который ничего не делает. Иначе говоря:
То есть, такие вопросы – не на преобразование типов, а на понимание, что если находится вне выражений, то это не объект, а блок.