Array.from()

Метод Array.from() створює новий екземпляр Array (дрібну копію) з подібного до масиву або ітерабельного об'єкта.

Синтаксис

Array.from(arrayLike[, mapFn[, thisArg]])

Параметри

arrayLike
Подібний до масиву або ітерабельний об'єкт, який треба перетворити на масив.
mapFn Optional
Функція Map для виклику на кожному елементі масиву.
thisArg Optional
Значення this для функції mapFn.

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

Новий екземпляр Array.

Опис

Array.from() дозволяє створювати масиви з:

  • подібних до масивів об'єктів (об'єктів з властивістю length та елементами, що мають числові індекси) або
  • ітерабельних об'єктів (об'єктів, з яких можна отримати елементи, таких як Map та Set).

Array.from() має необов'язковий параметр mapFn, який дозволяє виконати функцію map на кожному елементі масиву (або об'єкта підкласу), який створюється. Іншими словами, Array.from(obj, mapFn, thisArg) має той самий результат, що й Array.from(obj).map(mapFn, thisArg), тільки він не створює проміжний масив. Це особливо важливо для певних підкласів масивів, таких як типізовані масиви, оскільки проміжний масив обов'язково урізав би значення для перетворення у відповідний тип.

Властивість length методу from() дорівнює 1.

У ES2015, синтаксис класів дозволяє створення підкласів як для вбудованих класів, так і для тих, що створені користувачем; в результаті статичні методи, такі як Array.from "успадковуються" підкласами класу Array і створюють нові екземпляри підкласу, а не класу Array.

Приклади

Масив з рядка

Array.from('foo'); 
// [ "f", "o", "o" ]

Масив з об'єкта Set

const set = new Set(['foo', 'bar', 'baz', 'foo']);
Array.from(set);
// [ "foo", "bar", "baz" ]

Масив з об'єкта Map

const map = new Map([[1, 2], [2, 4], [4, 8]]);
Array.from(map);
// [[1, 2], [2, 4], [4, 8]]

const mapper = new Map([['1', 'a'], ['2', 'b']]);
Array.from(mapper.values());
// ['a', 'b'];

Array.from(mapper.keys());
// ['1', '2'];

Масив з подібного до масиву об'єкта (arguments)

function f() {
  return Array.from(arguments);
}

f(1, 2, 3);

// [ 1, 2, 3 ]

Використання стрілкових функцій та Array.from()

// Використання стрілкової функції в якості функції map
// для маніпулювання елементами
Array.from([1, 2, 3], x => x + x);      
// [2, 4, 6]


// Генерування послідовності чисел
// Оскільки масив ініціалізується значенням `undefined` на кожній позиції,
// значення `v` нижче дорівнюватиме `undefined`
Array.from({length: 5}, (v, i) => i);
// [0, 1, 2, 3, 4]

Генератор послідовності (range)

// Функція генератора послідовності (зазвичай відома як "range", напр. у Clojure, PHP та ін.)
const range = (start, stop, step) => Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step));

// Згенерувати числа у діапазоні 0..4
range(0, 4, 1);
// [0, 1, 2, 3, 4] 

// Згенерувати числа у діапазоні 1..10 з кроком 2 
range(1, 10, 2); 
// [1, 3, 5, 7, 9]

// Згенерувати алфавіт з допомогою Array.from, користуючись тим, що він впорядкований як послідовність
range('A'.charCodeAt(0), 'Z'.charCodeAt(0), 1).map(x => String.fromCharCode(x));
// ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]

Поліфіл

Метод Array.from був доданий до стандарту ECMA-262 у 6-й версії (ES2015); таким чином, він може не існувати у інших реалізаціях стандарту. Ви можете обійти цю проблему, вставивши наступний код на початку ваших скриптів, що дозволить використовувати метод Array.from у реалізаціях, які не мають його вбудованої підтримки. Цей алгоритм саме той, що визначений у ECMA-262, у 6-й версії, за умови, що Object та TypeError мають свої первинні значення і callback.call дорівнює первинному значенню Function.prototype.call. На додаток, оскільки справжні ітерабельні об'єкти не можуть мати поліфілу, ця реалізація не підтримує загальні ітерабельні об'єкти, визначені у 6-й версії ECMA-262.

// Функціональні кроки ECMA-262, версія 6, 22.1.2.1
if (!Array.from) {
  Array.from = (function () {
    var toStr = Object.prototype.toString;
    var isCallable = function (fn) {
      return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
    };
    var toInteger = function (value) {
      var number = Number(value);
      if (isNaN(number)) { return 0; }
      if (number === 0 || !isFinite(number)) { return number; }
      return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
    };
    var maxSafeInteger = Math.pow(2, 53) - 1;
    var toLength = function (value) {
      var len = toInteger(value);
      return Math.min(Math.max(len, 0), maxSafeInteger);
    };

    // Властивість length метода from дорівнює 1.
    return function from(arrayLike/*, mapFn, thisArg */) {
      // 1. Нехай C дорівнює значенню this.
      var C = this;

      // 2. Нехай items дорівнює ToObject(arrayLike).
      var items = Object(arrayLike);

      // 3. ReturnIfAbrupt(items).
      if (arrayLike == null) {
        throw new TypeError('Array.from requires an array-like object - not null or undefined');
      }

      // 4. Якщо mapfn дорівнює undefined, тоді нехай mapping дорівнює false.
      var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
      var T;
      if (typeof mapFn !== 'undefined') {
        // 5. інакше
        // 5. а Якщо IsCallable(mapfn) дорівнює false, викинути виняток TypeError.
        if (!isCallable(mapFn)) {
          throw new TypeError('Array.from: when provided, the second argument must be a function');
        }

        // 5. б. Якщо надано thisArg, нехай T дорівнює thisArg; інакше нехай T дорівнює undefined.
        if (arguments.length > 2) {
          T = arguments[2];
        }
      }

      // 10. Нехай lenValue дорівнює Get(items, "length").
      // 11. Нехай len дорівнює ToLength(lenValue).
      var len = toLength(items.length);

      // 13. Якщо IsConstructor(C) дорівнює true, тоді
      // 13. а. Нехай A дорівнює результату виклику внутрішнього метода С [[Construct]] 
      // зі списком аргументів, що містить єдиний елемент len.
      // 14. a. Інакше, нехай A дорівнює ArrayCreate(len).
      var A = isCallable(C) ? Object(new C(len)) : new Array(len);

      // 16. Нехай k дорівнює 0.
      var k = 0;
      // 17. Повторювати, доки k < len… (також кроки a - h)
      var kValue;
      while (k < len) {
        kValue = items[k];
        if (mapFn) {
          A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
        } else {
          A[k] = kValue;
        }
        k += 1;
      }
      // 18. Нехай putStatus дорівнює Put(A, "length", len, true).
      A.length = len;
      // 20. Повернути A.
      return A;
    };
  }());
}

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

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

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

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox for AndroidOpera for AndroidSafari on iOSSamsung InternetNode.js
fromChrome Full support 45Edge Full support 12Firefox Full support 32IE No support NoOpera Full support YesSafari Full support 9WebView Android Full support 45Chrome Android Full support 45Firefox Android Full support 32Opera Android Full support YesSafari iOS Full support YesSamsung Internet Android Full support Yesnodejs Full support 4.0.0

Legend

Full support  
Full support
No support  
No support

Див. також