Array.prototype.slice()

Метод slice() повертає дрібну копію частини масиву у новий масив, починаючи з begin і до end (не включаючи end), де begin та end є індексами елементів масиву. Початковий масив не змінюється.

Синтаксис

arr.slice([begin[, end]])

Параметри

begin Optional
Індекс на основі нуля, з якого починається копіювання.
Індекс може бути від'ємним, зазначаючи відступ з кінця послідовності. slice(-2) копіює останні два елементи послідовності.
Якщо begin не надано, slice починається з індексу 0.
Якщо begin більший за довжину послідовності, повертається порожній масив.
end Optional
Індекс на основі нуля до якого вібувається копіювання. slice копіює до, але не включаючи end.
Наприклад, slice(1,4) копіює з другого по четвертий елемент (елементи за індексами 1, 2 та 3).
Індекс може бути від'ємним, зазначаючи відступ з кінця послідовності. slice(2,-1) копіює з третього елемента по другий з кінця.
Якщо end пропущений, slice копіює до кінця послідовності (arr.length).
Якщо end більший за довжину послідовності, slice копіює до кінця послідовності (arr.length).

Значення, що повертається

Новий масив, який містить скопійовані елементи.

Опис

slice не змінює початковий масив. Він повертає дрібну копію елементів початкового масиву. Елементи початкового масиву копіюються у повернений масив наступним чином:

  • Для посилань на об'єкт (але не самих об'єктів), slice копіює посилання на об'єкт у новий масив. І початковий, і новий масиви посилатимуться на той самий об'єкт. Якщо цей об'єкт зміниться, зміни відобразяться у обох масивах, новому та початковому.
  • Для рядків, чисел та булевих значень (не об'єктів String, Number та Boolean), slice копіює значення у новий масив. Зміни у рядках, числах або булевих значеннях одного масиву не відображатимуться у іншому масиві.

Якщо новий елемент додано у якийсь з масивів, інший масив не зміниться.

Приклади

Повернути частину існуючого масиву

var fruits = ['Банан', 'Апельсин', 'Лимон', 'Яблуко', 'Манго'];
var citrus = fruits.slice(1, 3);

// fruits містить ['Банан', 'Апельсин', 'Лимон', 'Яблуко', 'Манго']
// citrus містить ['Апельсин','Лимон']

Використання slice

У наступному прикладі slice створює новий масив newCar з myCar. Обидва містять посилання на об'єкт myHonda. Коли колір myHonda змінюється на фіолетовий, обидва масиви відображають зміну.

// Використання slice, створення newCar з myCar.
var myHonda = { color: 'червоний', wheels: 4, engine: { cylinders: 4, size: 2.2 } };
var myCar = [myHonda, 2, 'чудовий стан', 'придбана 1997'];
var newCar = myCar.slice(0, 2);

// Вивести значення myCar, newCar та колір myHonda
// з обох масивів.
console.log('myCar = ' + JSON.stringify(myCar));
console.log('newCar = ' + JSON.stringify(newCar));
console.log('myCar[0].color = ' + myCar[0].color);
console.log('newCar[0].color = ' + newCar[0].color);

// Змінити колір myHonda.
myHonda.color = 'фіолетовий';
console.log('Новий колір Honda ' + myHonda.color);

// Вивести колір myHonda з обох масивів.
console.log('myCar[0].color = ' + myCar[0].color);
console.log('newCar[0].color = ' + newCar[0].color);

Скрипт запише:

myCar = [{color: 'червоний', wheels: 4, engine: {cylinders: 4, size: 2.2}}, 2,
         'чудовий стан', 'придбана 1997']
newCar = [{color: 'червоний', wheels: 4, engine: {cylinders: 4, size: 2.2}}, 2]
myCar[0].color = червоний 
newCar[0].color = червоний
Новий колір Honda фіолетовий
myCar[0].color = фіолетовий
newCar[0].color = фіолетовий

Подібні до масиву об'єкти

Метод slice також може перетворювати подібні до масиву об'єкти/колекції на нові об'єкти Array. Ви просто прив'язуєте метод до об'єкта. Аргументи всередині функції є прикладом подібного до масиву об'єкта.

function list() {
  return Array.prototype.slice.call(arguments);
}

var list1 = list(1, 2, 3); // [1, 2, 3]

Прив'язати можна функцією .call з Function.prototype, також можна скоротити запис, використовуючи  [].slice.call(arguments) замість Array.prototype.slice.call. В будь-якому випадку, все можна спростити за допомогою bind.

var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.call.bind(unboundSlice);

function list() {
  return slice(arguments);
}

var list1 = list(1, 2, 3); // [1, 2, 3]

Оптимізація кросбраузерної поведінки

Хоча об'єкти середовища виконання (такі як об'єкти DOM) за специфікацією не зобов'язані відповідати поведінці Mozilla при перетворенні методом Array.prototype.slice, і IE < 9 цього не робить, версії IE починаючи від 9-ї дозволяють це. Використання шима дозволяє  створити надійну кросбраузерну поведінку. Поки інші сучасні переглядачі підтримують цю можливість, як нині роблять IE, Mozilla, Chrome, Safari та Opera, розробники, які читають (підтримують для об'єктів DOM) slice-код, що покладається на цей шим, не будуть введені в оману семантикою; вони спокійно можуть покладатися на семантику, щоб реалізувати тепер вже де-факто стандартну поведінку. (Шим також виправляє роботу IE з другим аргументом slice(), коли він явно заданий як null/undefined, чого більш ранні версії IE також не дозволяли, але всі сучасні переглядачі, в тому числі IE >= 9, зараз дозволяють.)

/**
 * Шим для "виправлення" слабкої підтримки IE (IE < 9) використання slice
 * на об'єктах середовища, таких як NamedNodeMap, NodeList та HTMLCollection
 * (технічно, оскільки об'єкти середовища були залежні від реалізації,
 * принаймні до ES2015, IE не мав потреби у цій функціональності.)
 * Також працює для рядків, виправляє IE < 9, дозволяючи явно задане значення
 * undefined другим аргументом (як у Firefox) та запобігає помилкам
 * при виклику на інших об'єктах DOM.
 */
(function () {
  'use strict';
  var _slice = Array.prototype.slice;

  try {
    // Не можна використовувати з елементами DOM у IE < 9
    _slice.call(document.documentElement);
  } catch (e) { // Не працює у IE < 9
    // Працюватиме для справжніх масивів, подібних до масивів об'єктів, 
    // NamedNodeMap (атрибутів, сутностей, нотацій),
    // NodeList (напр., getElementsByTagName), HTMLCollection (напр., childNodes),
    // і не схибить на інших об'єктах DOM (як на елементах DOM у IE < 9)
    Array.prototype.slice = function(begin, end) {
      // IE < 9 не любить undefined в якості аргументу end
      end = (typeof end !== 'undefined') ? end : this.length;

      // Для об'єктів Array використовуємо рідну функцію slice
      if (Object.prototype.toString.call(this) === '[object Array]'){
        return _slice.call(this, begin, end); 
      }

      // Для подібних до масивів об'єктів робимо це самостійно.
      var i, cloned = [],
        size, len = this.length;

      // Обробляємо від'ємне значення "begin"
      var start = begin || 0;
      start = (start >= 0) ? start : Math.max(0, len + start);

      // Обробляємо від'ємне значення "end"
      var upTo = (typeof end == 'number') ? Math.min(end, len) : len;
      if (end < 0) {
        upTo = len + end;
      }

      // Очікуваний розмір нового масиву
      size = upTo - start;

      if (size > 0) {
        cloned = new Array(size);
        if (this.charAt) {
          for (i = 0; i < size; i++) {
            cloned[i] = this.charAt(start + i);
          }
        } else {
          for (i = 0; i < size; i++) {
            cloned[i] = this[start + i];
          }
        }
      }

      return cloned;
    };
  }
}());

Специфікації

Специфікація Статус Коментар
ECMAScript Latest Draft (ECMA-262)
The definition of 'Array.prototype.slice' in that specification.
Draft
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Array.prototype.slice' in that specification.
Standard
ECMAScript 5.1 (ECMA-262)
The definition of 'Array.prototype.slice' in that specification.
Standard
ECMAScript 3rd Edition (ECMA-262) Standard Початкове визначення. Реалізовано у JavaScript 1.2.

Сумісність з веб-переглядачами

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox for AndroidOpera for AndroidSafari on iOSSamsung InternetNode.js
sliceChrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 4Opera Full support YesSafari Full support YesWebView Android Full support YesChrome Android Full support 18Firefox Android Full support 4Opera Android Full support YesSafari iOS Full support YesSamsung Internet Android Full support Yesnodejs Full support Yes

Legend

Full support  
Full support

Див. також