Метод slice()
є одним з найбільш потужних та часто використовуваних методів у JavaScript. А з розвитком React та інших функціонально-орієнтованих практик, метод стає ще важливішим з двох ключових причин:
- Функціональне програмування, особливо високорівневі функції, широко працюють зі списками даних.
- Функціональне програмування вимагає чистих функцій, тобто функцій, що не викликають побічних ефектів та не змінюють свої вхідні дані.
Метод array slice
у JavaScript задовольняє обидва критерії
Метод slice
надає механізм для створення поверхневої копії підмножини списку, без зміни початкового списку. Таким чином, отримуємо ключовий будівельний блок для написання функціонального JavaScript.
У статті ми поглянемо на метод slice
у дії та попрактикуємось на восьми прикладах його можливого застосування.
Зверніть увагу: метод slice
не варто плутати з методом splice
, який модифікує масив. У той же час slice
залишає вихідний масив недоторканим, повертаючи лише копію обраних елементів.
Як працює Array Slice
Перед тим як ми поринемо у більш складні варіанти застосування, оглянемо базові приклади роботи зі slice
.
Як свідчить документація MDN, метод slice
може приймати до двох аргументів:
arr.slice([begin[, end]])
Аргумент begin
— 0-індекс, що визначає, де почати вилучення, у той же час аргумент end
— 0-індекс, що визначає завершення фрагменту.
Метод slice
створює копію масиву, починаючи з begin
— і до end
(не включно). Також працює з від'ємними індексами, що означають відлік з кінця масиву.
Базове застосування
Перші чотири приклади висвітлюватимуть ключову функціональність slice
.
1. Просте копіювання
const arr2 = arr.slice();
Slice
без аргументів представляє просте поверхневе копіювання. У сучасному JavaScript доцільніше використовувати оператор «spread» для таких завдань. Однак, при роботі зі старішою кодовою базою або без здійснення збірки, що використовує Babel, slice
все ще стане у пригоді.
2. Підмасив, що починається з N
Найпростіший спосіб використання методу slice
— просто охопити всі елементи масиву, починаючи з N.
Наприклад, вам необхідно вилучити перший елемент з масиву та використати його, повернувши масив. Однак, зробити це треба без модифікації початкового масиву.
function useOne(arr) {
const usedItem = arr[0];
// робіть щось з usedItem
return arr.slice(1);
}
3. Останні N елементів масиву
Інший варіант використання slice
— охоплення кінця масиву, звертаючи увагу на той факт, що передавши від'ємний індекс до методу, відлік починається з кінця масиву.
Можливість передати від'ємний індекс спрощує процес виокремлення елементів. Наприклад, вам необхідно вилучити лише три елементи:
const last3 = arr.slice(-3)
4. Перші N елементів
Щоб вилучити частину масиву до певного елемента, необхідно використати другий аргумент — end
.
Коли передано обидва елементи, метод slice
повертає набір елементів, починаючи з begin
— і до end
, не включно.
Оскільки масиви у JavaScript починаються з нульового індексу, набагато легше вилучити перші N елементів:
const first4 = arr.slice(0, 4)
5. Внутрішній сегмент, починаючи з m
Узагальнимо викладене способом №5. Що, якщо ми хотіли б використовувати slice
для отримання частини масиву, починаючи з будь-якого індексу.
З цією метою, необхідно перейти від (begin, length)
до (begin, end)
. На щастя, математика проста: визначимо нескладну функцію для реалізації:
function pullSegment(arr, begin, length) {
return arr.slice(begin, begin + length);
}
Працюємо з об'єктами Array-like
Метод slice
також може застосовуватись до array-like об'єктів. Такі об'єкти поводяться, здебільшого, як масиви, але такими не є. Тобто це будь-які об'єкти, що мають значення length
, а доступ до них можна отримати за допомогою індексів. Однак, методи масивів до них не застосовуються.
Декілька прикладів містять arguments
(ключове слово для доступу до всіх аргументів, що передаються функції), NodeLists
(повернений з будь-якого DOM API метод, що повертає список гілок) та навіть сирі об'єкти, що використовують числові індекси та додають атрибут length
.
Щоб застосовувати метод slice
до об'єкта array-like, необхідно посилатися на нього прямо з Array.prototype
таким чином:
Array.prototype.slice.call(arguments);
6. Конвертувати об'єкти array-like у масиви
Поширеним випадком застосування оператора slice
для масивоподібних об'єктів є перетворення їх у справжні масиви. Наприклад:
const args = Array.prototype.slice.call(arguments);
Навіщо це потрібно? Для отримання доступу до методів масивів. Наприклад, уявіть функцію, що виглядає наступним чином:
function addOne() {
return arguments.map(i => i+1);
}
Нам здається, що вона працюватиме. Натомість отримаємо наступне:
> addOne(1, 2, 3)
TypeError: arguments.map is not a function
at test (repl:2:18)
at repl:1:1
at ContextifyScript.Script.runInThisContext (vm.js:44:33)
at REPLServer.defaultEval (repl.js:239:29)
at bound (domain.js:301:14)
at REPLServer.runBound [as eval] (domain.js:314:12)
at REPLServer.onLine (repl.js:440:10)
at emitOne (events.js:120:20)
at REPLServer.emit (events.js:210:7)
at REPLServer.Interface._onLine (readline.js:279:10)
Така ситуація виникає тому що arguments
насправді не масив, а масивоподібний об'єкт. Ви можете застосувати цю функцію, використовуючи slice
наступним чином:
function addOne() {
return Array.prototype.slice.call(arguments).map(i => i+1);
}
І тепер отримаємо очікуваний результат:
> addOne(1, 2, 3)
[ 2, 3, 4 ]
7. Дозволяємо довільне число аргументів
Іноді потрібно дозволити передавати у функцію довільне число аргументів.
Новіші версії JavaScript представляють так званий rest синтаксис для обробки таких ситуацій, але якщо ви застрягли з підтримкою старіших браузерів без системи транспіляції, ви можете досягнути того ж ефекту зі slice
:
function myFunc(a, b) {
const extraArgs = Array.prototype.slice.call(arguments, 2);
}
Тепер ми можемо викликати myFunc
з довільним числом аргументів, наприклад:
myFunc(1, 2, 3, 4, 5, 6, 7, 8)
Наприкінці отримаєте a === 1
, b === 2
, та extraArgs === [3, 4, 5, 6, 7, 8]
.
Функціональні маніпуляції з масивами
Ще одна величезна область застосування slice
— функціональне управління масивами, без зміни вихідного масиву.
8. Зміна визначеного індексу в масиві
Потужний та поширений спосіб використання slice
у функціональному контексті полягає у заміні значення певного індексу у масиві.
З імперативним підходом це досить просто: ви просто призначаєте нове значення, а у функціональному програмуванні усе складніше. Ви не можете модифікувати вихідний масив.
Натомість, якщо об'єднати slice
з новим оператором розширення у JavaScript, то повернеться новий масив, що ідентичний початковому, але починається з індексу, який ви хотіли б оновити.
Часткове застосування функцій
Одним з поширених шаблонів у функціональному програмуванні є часткове застосування функцій: виклик функції з меншою кількістю аргументів і повернення функції, що приймає інші аргументи.
Шаблон дозволяє створювати функціїї, що мають різні попередньо застосовані параметри. Такий підхід робить ваш код придатним для повторного використання.
У той час, як більш чисті функціональні мови, як Haskell підтримують часткове застосування функцій, у JavaScript ми реалізуємо такий підхід зі slice
.
var partial = function() {
const fn = arguments[0];
const args = Array.prototype.slice.call(arguments, 1);
// Повертає функцію, що викликає fn
return function() {
var remainingArgs = Array.prototype.slice.call(arguments);
return fn.apply(this, args.concat(remainingArgs));
}
}
Ще немає коментарів