MDN wants to learn about developers like you: https://qsurvey.mozilla.com/s3/MDN-dev-survey

Non-standard. Do not use!
Сокращенный синтаксис создания массивов не стандартен. В будущем используйте Array.prototype.map, Array.prototype.filter, Стрелочные функции и spread syntax.

Синтаксис array comprehension - это JavaScript-выражение, которое позволяет быстро создавать новый массив из существующего. Аналогичные сокращения существуют во многих других языках программирования.

Ниже показаны различия со старым синтаксисом Array Comprehension в SpiderMonkey, основанном на черновиках для ECMAScript 4.

Синтаксис

[for (x of итерируемый_объект) x]
[for (x of итерируемый_объект) if (условие) x]
[for (x of итерируемый_объект) for (y of итерируемый_объект) x + y]

Описание

Внутри сокращения допустимо использование двух видов компонентов:

Итерация for-of всегда является первым компонентом. Допустимо использование нескольких for-of итераций или условных операторов if.

Сокращённый синтаксис создания массивов был предложен к стандартизации в ECMAScript 2016, он предоставлял удобный сокращения для создания новых массивов из других массивов. Сокращения могут быть использованы вместо вызовов map() и filter() или их комбинаций.

Следующий пример показывает, как из массива чисел создаётся новый массив чисел с с удвоенным значением.

var numbers = [1, 2, 3, 4];
var doubled = [for (i of numbers) i * 2];
console.log(doubled); // logs 2,4,6,8

Это эквивалентно следующей операции с map():

var doubled = numbers.map(i => i * 2);

Сокращённый синтаксис может быть использован также для выбора элементов по определённому условию. Вывод четных чисел:

var numbers = [1, 2, 3, 21, 22, 30];
var evens = [for (i of numbers) if (i % 2 === 0) i];
console.log(evens); // logs 2,22,30

filter() может использоваться для той же цели:

var evens = numbers.filter(i => i % 2 === 0);

Стили операторов map() и filter() можно одновременно использовать в одном сокращённом выражении. Далее фильтруются только четные числа, а затем создаётся массив с их удвоенным значением:

var numbers = [1, 2, 3, 21, 22, 30];
var doubledEvens = [for (i of numbers) if (i % 2 === 0) i * 2];
console.log(doubledEvens); // logs 4,44,60

Квадратные скобки обозначают неявный блок. Новый переменные (такие как  "i" в примере выше) трактуются, как если бы они объявлялись с использованием let. Это значит, что эти переменные недоступны извне.

Входными данными необязательно может быть массив; также можно использовать итераторы и генераторы.

Даже строки могут подаваться на вход; можно делать то же, что с filter и map (но с массивоподобными объектами):

var str = 'abcdef';
var consonantsOnlyStr = [for (c of str) if (!(/[aeiouAEIOU]/).test(c)) c].join(''); // 'bcdf'
var interpolatedZeros = [for (c of str) c + '0' ].join(''); // 'a0b0c0d0e0f0'

Для предупреждения конвертации в число (в данном конкретном примере) использвалась функция join().

Примеры

Простые сокращения

[for (i of [ 1, 2, 3 ]) i*i ]; 
// [ 1, 4, 9 ]

var abc = [ "A", "B", "C" ];
[for (letters of abc) letters.toLowerCase()];
// [ "a", "b", "c" ]

Сокращения с условным оператором "if"

var years = [ 1954, 1974, 1990, 2006, 2010, 2014 ];
[for (year of years) if (year > 2000) year];
// [ 2006, 2010, 2014 ]
[for (year of years) if (year > 2000) if(year < 2010) year];
// [ 2006], the same as below:
[for (year of years) if (year > 2000 && year < 2010) year];
// [ 2006] 

Сокращения в сравнении с map и filter

Простой способ понять синтаксис Array Comprehension - это сравнить его с методами Array map и filter:

var numbers = [ 1, 2, 3 ];

numbers.map(function (i) { return i * i });
numbers.map(i => i*i);
[for (i of numbers) i*i ];
// all are [ 1, 4, 9 ]

numbers.filter(function (i) { return i < 3 });
numbers.filter(i => i < 3);
[for (i of numbers) if (i < 3) i];
// all are [ 1, 2 ]

Сокращения с двумя массивами

Использование двух итераторов for-of для работы с двумя массивами:

var numbers = [ 1, 2, 3 ];
var letters = [ "a", "b", "c" ];

var cross = [for (i of numbers) for (j of letters) i+j];
// [ "1a", "1b", "1c", "2a", "2b", "2c", "3a", "3b", "3c" ]

var grid = [for (i of numbers) [for (j of letters) i+j]];
// [
//  ["1a", "1b", "1c"],
//  ["2a", "2b", "2c"],
//  ["3a", "3b", "3c"]
// ]

[for (i of numbers) if (i > 1) for (j of letters) if(j > "a") i+j]
// ["2b", "2c", "3b", "3c"], the same as below:

[for (i of numbers) for (j of letters) if (i > 1) if(j > "a") i+j]
// ["2b", "2c", "3b", "3c"]

[for (i of numbers) if (i > 1) [for (j of letters) if(j > "a") i+j]]
// [["2b", "2c"], ["3b", "3c"]], not the same as below:

[for (i of numbers) [for (j of letters) if (i > 1) if(j > "a") i+j]]
// [[], ["2b", "2c"], ["3b", "3c"]]

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

Изначально было в черновике ECMAScript 2015, но исключено в ревизии 27 (Август 2014). Смотрите старые ревизии ES2015 для уточнения семантики.

Совместимость с браузерами

Возможность Chrome Firefox (Gecko) Internet Explorer Opera Safari
Базовая поддержка Нет 30 (30) Нет Нет Нет
Возможность Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Базовая поддержка Нет Нет 30.0 (30) Нет Нет Нет

Специфика работы SpiderMonkey

  • let не поддерживается как идентификатор, так как он доступен только в  JS версии 1.7 и XUL-скриптах.
  • Деструктуризация сокращений не поддерживается (баг 980828).

Отличия от старой версии JS1.7/JS1.8

Сокращения из JS1.7/JS1.8 были исключены из движка Gecko, начиная с версии 46 (баг 1220564).

Старый синтаксис (не используйте его больше!):

[X for (Y in Z)]
[X for each (Y in Z)]
[X for (Y of Z)]

Различия:

  • Сокращения в ESNext создают одну область для элемента "for" вместо области для всех элементов for в целом.
    • Old: [()=>x for (x of [0, 1, 2])][1]() // 2
    • New: [for (x of [0, 1, 2]) ()=>x][1]() // 1, каждая итерация создаёт свежую связку с x.
  • Сокращения в ESNext начинаются с "for" вместо присваиваемой переменной.
    • Old: [i * 2 for (i of numbers)]
    • New: [for (i of numbers) i * 2]
  • Сокращения в ESNext могут иметь несколько компонентов if и for.
  • Сокращения в ESNext работают только с итерациями вида for...of и не работают с for...in.

Смотрите Bug 1220564, comment 42 для внесения предложений по коду.

Смотрите также

Метки документа и участники

 Внесли вклад в эту страницу: pk.prog, Frenk1, krvital
 Обновлялась последний раз: pk.prog,