* something * if * expression * синтаксис в JavaScript (FF)

Я видел несколько примеров, показывающих, что Firefox поддерживает какой-то синтаксис JavaScript по строкам *something* if *expression*;.

В качестве примера того, о чем я говорю, см. эту статью MDN, которая содержит следующий пример:

var evens = [i for each (i in range(0, 21)) if (i % 2 == 0)];

Мои вопросы:

Какое имя будет дано для описания такого синтаксиса? Я в основном хочу знать это, чтобы я мог Google и больше узнать об этом. Я попробовал Google Googling лучшее, что я могу придумать, но не смог собрать правильные условия для получения полезных результатов.

Может ли этот синтаксис существовать в других местах за пределами понимания массива? Я чувствую, что видел другие примеры использования этого вне массива (например, в примере выше), но я я не уверен.

Где я могу узнать больше об этом синтаксисе?

Поддерживают ли другие браузеры это помимо Firefox?

Является ли эта функция в ES5 или запланирована для ES-гармонии?

Ответ 1

Как отмечали другие, это называется "Array Comprehensions", и это одна из многих, многих функций, предлагаемых для ECMAScript Harmony:

http://wiki.ecmascript.org/doku.php?id=harmony:array_comprehensions

Однако, как и в большинстве функций "Гармония" Гармонии, я не думаю, что существует какое-то реальное представление о том, действительно ли оно будет включено в окончательный выпуск. Вы можете использовать его в Firefox как часть "JavaScript 1.7" (туманная "стандартная" спецификация, которая действительно применима только к материалам на основе Mozilla); однако вам лучше избегать синтаксиса, специфичного для FF, особенно если это приведет к синтаксическим ошибкам в других браузерах.

Вы можете узнать больше об этом, выполнив поиск Google для "Array Comprehensions", но, как я уже упоминал, это не очень полезный инструмент из-за его специфики для Mozilla.

Вы можете добиться подобного эффекта без большого количества кода, используя метод reduce() Array, введенный в ES5:

//JavaScript has no "range" function, so let make one
var range = function (begin, length) { 
    var i, ret = [];
    for (i = begin; i < begin + length; i++) {
        ret.push(i);
    }
    return ret;
};

var evens = range(0, 21).reduce(function (arr, cur) { 
    if (cur % 2 === 0) arr.push(cur);
    return arr; 
}, []);

Это может быть немного многословным по сравнению с тем, что вы искали (даже имея в виду, что нам нужно было создать функцию range()). Но это относительно компактное решение, которое не требует много "настройки" и в основном относится к решению проблемы: фильтрации элементов из одного массива для формирования второго массива.

Мне удалось свести его к однострочному, но он немного неудобен для поддержки, поэтому я решил предложить две версии строк. Если вас интересует однострочный, вот он:

//Don't forget to define "range()"
var evens = range(0, 21).reduce(function (arr, cur) { 
    return (cur % 2 === 0) ? (arr.push(cur) && arr) : arr; 
}, []);

Опять же, это код ES5. Если вы хотите, чтобы он работал в старых браузерах, вам нужно придумать прокладку, чтобы обеспечить поддержку Array.reduce(). В MDN есть один из них:

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/Reduce

UPDATE:

Похоже, я должен был использовать filter() вместо reduce(). Делает код намного чище. Спасибо ОП за предложение!

var evens = range(0,21).filter(function (cur) { return cur % 2 === 0; });

Опять же, filter() - ES5, поэтому вам понадобится прокладка, чтобы обеспечить правильную работу в старых браузерах.

Ответ 2

Этот тип утверждения известен как понимание списка. Python имеет хорошие примеры с очень похожим синтаксисом.