arrayIterators principle - garevna/js-course GitHub Wiki

🎓 Итерирующие методы массивов

Выведя в консоль свойство prototype конструктора массивов, можно убедиться, что эти структуры данных наследуют много методов, и некоторые из них мы уже знаем

Array.prototype
▼ [constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]
  ► concat: ƒ concat()
  ► constructor: ƒ Array()
  ► copyWithin: ƒ copyWithin()
  ► entries: ƒ entries()
  ► every: ƒ every()
  ► fill: ƒ fill()
  ► filter: ƒ filter()
  ► find: ƒ find()
  ► findIndex: ƒ findIndex()
  ► flat: ƒ flat()
  ► flatMap: ƒ flatMap()
  ► forEach: ƒ forEach()
  ► includes: ƒ includes()
  ► indexOf: ƒ indexOf()
  ► join: ƒ join()
  ► keys: ƒ keys()
  ► lastIndexOf: ƒ lastIndexOf()
    length: 0
  ► map: ƒ map()
  ► pop: ƒ pop()
  ► push: ƒ push()
  ► reduce: ƒ reduce()
  ► reduceRight: ƒ reduceRight()
  ► reverse: ƒ reverse()
  ► shift: ƒ shift()
  ► slice: ƒ slice()
  ► some: ƒ some()
  ► sort: ƒ sort()
  ► splice: ƒ splice()
  ► toLocaleString: ƒ toLocaleString()
  ► toString: ƒ toString()
  ► unshift: ƒ unshift()
  ► values: ƒ values()
  ► Symbol(Symbol.iterator): ƒ values()
  ► Symbol(Symbol.unscopables): {copyWithin: true, entries: true, fill: true, find: true, findIndex: true, …}
  ► __proto__: Object

Часть методов, с которыми мы уже знакомы, выполняют какую-то операцию с массивом ( добавляют элемент в массив, удаляют или заменяют элементы в массиве, объединяют несколько массивов в один и т.д. )

Итерирующие методы перебирают элементы массива один за другим строго в порядке возрастания их индексов ( за исключением reduceRight )

В процессе перебора значений происходит вызов указанной нами функции, которая и получает очередной элемент массива в качестве аргумента

Методы массивов

Обычные Итерирующие
concat entries
copyWithin every
fill filter
flat ⚠️ find
includes findIndex
indexOf flatMap ⚠️
join forEach
lastIndexOf keys
pop map
push reduce
reverse reduceRight
shift some
slice sort
splice values
unshift

Группа итерирующих методов массивов - пример реализации функциональной парадигмы в ООП

Точнее, mix двух парадигм программирования
Mix - потому что мы передаем этим методам в аргументах не только функцию, но и ссылку на объект

Обязательный первый аргумент, передаваемый методу в момент вызова - функция

function func ( arrayElement ) {
    console.log ( arrayElement )
}

[ 7, "D", false ]
    .forEach ( func )

Обязательный формальный параметр функции ( func ) - текущее значение элемента массива ( arrayElement )

Функция ( назовем ее условно callback ) будет вызвана на каждой итерации ( для каждого элемента массива )

☕ Принцип работы итерирующих методов
var arr = [ "google", "service", "user" ]

function test ( elem ) {
    console.log ( elem )
}

Array.prototype.sampleMethod = function ( callback ) {
    for ( var item of this ) 
        callback ( item )
}

arr.sampleMethod ( test )

Собственно, эти методы не изменяют исходный массив, поэтому алгоритм их работы скорее можно представить так:

var arr = [ "google", "service", "user", 0, false ]

function test ( elem ) {
    return `${ typeof elem === "string" ? elem : "default" }`
}

Array.prototype.sampleMethod = function ( callback ) {
    var res = []
    for ( var item of this ) {
        res.push ( callback ( item ) )
    }
    return res
}

arr.sampleMethod ( test )

Функция, передаваемая методу, может иметь больше формальных параметров,
но остальные два являются опциональными ( необязательными )

☕ 1️⃣ второй параметр - идекс текущего элемента массива
var arr = [ "google", "service", "user" ]

function test ( elem, index ) {
    return `${index}: ${elem}`
}

Array.prototype.sampleMethod = function ( callback ) {
    var res = []
    for ( var item of this ) 
        res.push (
            callback (
                item,
                this.indexOf ( item )
            )
        )
    return res
}

console.log ( arr.sampleMethod ( test ) )
☕ 2️⃣ третий параметр - ссылка на итерируемый массив
var arr = [ "google", "service", "user", 0, false ]

function test ( elem, index, ref ) {
    var tmp = typeof elem === "string" ? 
        ref.splice ( index, 1, true )[0] :
        null
    return ref [ index ]
}

Array.prototype.sampleMethod = function ( callback ) {
    var res = []
    for ( var item of this ) {
        res.push (
            callback (
                item,
                this.indexOf ( item ),
                this
            )
        )
    }
    return res
}

arr.sampleMethod ( test )
☕ 3️⃣

Функция, передаваемая методу в качестве первого аргумента, может быть анонимной, объявленной непосредственно в вызове метода

var  numbers = [ 8, 4, 9, 7 ]

Array.prototype.sampleMethod = function ( callback ) {
    var res = []
    for ( var item of this ) {
        res.push (
            callback (
                item,
                this.indexOf ( item ),
                this
            )
        )
    }
    return res
}

numbers.sampleMethod (
    function ( item, index, arr ) {
        console.log ( index, arr.indexOf( item ) === index )
        console.log ( index, arr [ index ] === item )
    }
)

Передача контекста

Кроме обязательного первого аргумента - ссылки на функцию

каждый метод имеет необязательный ( опциональный ) второй аргумент - ссылку на контекст вызова

( т.е. внутри метода this будет указывать на этот объект )

☕ 4️⃣
var numbers = [ 8, 4, 9, 7 ]
var alter = [ "google", 5, "figure", 11 ]

Array.prototype.sampleMethod = function ( callback, context ) {
    var res = []
    for ( var item of this ) {
        res.push (
            callback.call (
                context,
                item,
                this.indexOf ( item ),
                this
            )
        )
    }
    return res
}

var sample = numbers.sampleMethod (
    function ( item, index, arr ) {
        console.log ( this [ index ] )
        console.log ( arr )
    },
    alter
)

Итак, функция sample получает в переменной arr ссылку на исходный массив numbers, а this внутри функции sample указывает на массив alter

⚠️ **GitHub.com Fallback** ⚠️