JavaScript | Array | keys

JavaScript | Array | keys

Синтаксис метода keys()

Array.prototype.keys ( )

 

Логика работы метода keys()

Выполняются следующие шаги:

1. Пусть O будет ? ToObject(значение this).
2. Вернуть CreateArrayIterator(O, key).

 

Как работает итератор массивов в случае метода keys()?

Есть массив:

var massiv = ["efim", "360", ".", "ru"]

Мы создаём итератор массива и кладём его в переменную iterator

var iterator = massiv.keys()

У итератора массива есть свой собственный метод next() при помощи которого он обходит массив.

Создали итератор массива методом keys() - JavaScript
Создали итератор массива методом keys() — JavaScript

Каждый вызов next() делает шаг вперёд по массиву. Самостоятельное «шагание» вне других методов и функций бесполезно. Итератор должен вызываться «параллельно» вместе с остальными методами.

Давайте посмотрим, что возвращает шаг итератора массива.

Делаем первый шаг — первый раз вызываем next()

iterator.next()

Нам вернулся объект с двумя свойствами.

Первый шаг итератора массива - JavaScript
Первый шаг итератора массива — JavaScript

Ключ value хранит значение индекса первого элемента массива. На первом шаге «value0«. Ключ done хранит состояние выполнения итераций над массивом. На первом шаге «donefalse«

Делаем второй шаг

Второй шаг итератора массива - JavaScript
Второй шаг итератора массива — JavaScript

Делаем третий шаг

Третий шаг итератора массива - JavaScript
Третий шаг итератора массива — JavaScript

Делаем четвёртый шаг — это шаг на последний элемент массива

Четвёртый шаг итератора массива - JavaScript
Четвёртый шаг итератора массива — JavaScript

Делаем пятый шаг

Пятый шаг итератора массива - JavaScript
Пятый шаг итератора массива — JavaScript

На пятом шаге итератор массива возвращает объект с «valueundefined» и «donetrue«. Это значит, что итератор массива дошёл до конца массива и элементов больше нет.

Когда мы делаем шаги по массиву, то в этот момент мы можем извлекать номера индексов и использовать их в решениях своих задач.

 

 

Как использовать метод keys() у массивов?

Задача — Сравнение массивов

Есть 2 массива:

var a = [1, 2, 3, 4]
var b = [1, 2, 3, "4"]

Нам нужно сравнить 2 массива на равенство. Длины массивов совпадают, поэтому первое условие равенства массивов выполняется. Для сравнения будем использовать метод filter() и метод keys().

Метод filter() может принимать 2 параметра:

  1. Функцию, которая возвращает true или false
  2. Объект this для каждого вызова (тут будет наш итератор массива)

Вариант 1

Если массивы равны, то длина отфильтрованного массива должна равняться длине оригинального массива

a.filter( i => i === b[x.next().value], x=b.keys() )
[1, 2, 3]

В этом условии длина фильтрованного меньше длины оригинального массива. Значит массивы не равны.

Вариант 2

Если массивы не равны, то длина отфильтрованного массива будет больше нуля. То есть фильтрованный массив найдёт элемент, который не будет похож.

a.filter( i => i !== b[x.next().value], x=b.keys() )
[4]

В этом условии длина фильтрованного массива равна «1». В нём хранится элемент, который не совпал значением.

 

Задача — Получение индексов элементов с одинаковыми значениями

Есть массив с одинаковыми значениями «11»:

var massiv = [11, 22, 33, 11, 44, 11, 55, 66]

Как получить индексы элементов с одинаковыми значениями «11»?

massiv.map(i => i==11 ? x.next().value : x.next().done, x=massiv.keys()).filter(i => i !== false)
[0, 3, 5]

Сначала мы обошли элементы массива методом map(). В качестве this для функции обратного вызова мы использовали итератор массива по переменной massiv.

На каждом шаге метода map() мы проверяли условие равенства текущего элемента со значением «11«. Вместе с map() шагал и наш итератор массива. Если условие было верным, тогда мы возвращали индекс элемента, который доставали из ключа value объекта, возвращаемого шагом next(). Если условие было неверным, то мы возвращали значение ключа done.

 

Мы применили тернарный оператор (условие ? возвращаем если условие верное : возвращаем если условие неверное), чтобы упростить вид записи.

Метод map() вернул нам такой вариант массива:

[0, false, false, 3, false, 5, false, false]

Удобно то, что в нашем случае мы никогда не увидим true в качестве значения элемента преобразованного массива. Только индексы и false.

Получили индексы элементов с одинаковыми значениями 11 в массиве - JavaScript
Получили индексы элементов с одинаковыми значениями 11 в массиве — JavaScript

 

Информационные ссылки

JavaScript | Как получить индексы элементов с одинаковыми значениями в массиве?

Стандарт ECMAScript — Раздел «23.1.3.16 Array.prototype.keys ( )» — https://tc39.es/ecma262/#sec-array.prototype.keys