Czy Mogę ustąpić z funkcji wewnętrznej?

Z generatorami ES6 widzę taki kod:

var trivialGenerator = function *(array) {
    var i,item;
    for(var i=0; i < array.length; i++){
        item = array[i];
        yield item;
    };
};

Czy można zamiast tego napisać coś bardziej podobnego do poniższego kodu?

var trivialGenerator = function *(array) {
    array.forEach(function *(item){
        yield item;
    });
};

Pytam, bo klasyczna pętla for jest obrzydliwością.

Author: Max Heiber, 2015-03-28

2 answers

Nie, Nie możesz użyć yield wewnątrz funkcji wewnętrznej. Ale w Twoim przypadku nie potrzebujesz go. Zawsze możesz użyć for-of pętla zamiast forEach metoda. Będzie wyglądać znacznie ładniej i można użyć continue, break, yield w środku:

var trivialGenerator = function *(array) {
    for (var item of array) {
        // some item manipulation
        yield item;
    }
}

Możesz użyć for-of, Jeśli masz jakieś manipulacje z przedmiotem w środku. W przeciwnym razie absolutnie nie musisz tworzyć tego generatora, ponieważ array mA iterator interfejs natywnie.

 40
Author: alexpods,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-30 06:37:15

Nie, Nie można ustąpić od wywołania zwrotnego(technicznie rzecz biorąc, nie jest to "funkcja wewnętrzna", co oznacza coś innego). Oczywiście nie ma sposobu, aby wywołać {[13] } z odpowiednikiem *, lub, jeśli samo wywołanie zwrotne jest generatorem, aby powiedzieć forEach aby wywołać wywołanie zwrotne z yield *.

Jedną z alternatyw jest zapisanie funkcji forEachGen w następujący sposób:

function *forEachGen(array, fn) { for (var i of array) yield *fn(i); }

Zasadniczo przeniesienie pętli for do forEachGen. Definiowanie małego generatora próbek jako

function *yieldSelf(item) { yield item; }

forEachGen będzie używany as

yield *forEachGen(array, yieldSelf);

Zakłada to, że wywołanie zwrotne jest generatorem, jak wydaje się sugerować, że chcesz w swoim przykładzie. Jeśli wywołanie zwrotne było ROF (zwykła stara funkcja), takie jak

function returnSelf(item) { return item; }

Wtedy będzie

function *forEachGen(array, fn) { for (var i of array) yield fn(i); }

Używany jako

yield *forEachGen(array, returnSelf);

Jeśli nie masz nic przeciwko dodaniu tego do prototypu tablicy, to

Object.defineProperty(Array.prototype, 'forEachGen', { value :
    function *(fn) { for (i of this) yield fn(i); }
});

To zrób

yield *array.forEachGen(yieldSelf)
Możesz być zainteresowany http://fitzgen.github.io/wu.js / , która definiuje wrapper dla generatorów metodami takimi jako forEach na opakowaniu.

async / await

Z await, powinieneś być w stanie wykonać następujące czynności.

Zdefiniuj trywialne wywołanie zwrotne, które po prostu zwraca obietnicę dla siebie.

async function returnSelf(item) { return await item; }

forEachAsync mapuje tablicę wejściową do tablicy obietnic i używa await * do tworzenia i zwracania obietnicy dla wszystkich gotowych obietnic.

async function forEachAsync(values, fn) {
  return await *values.map(returnSelf);
}
Możemy traktować wynik jako zwykłą obietnicę i wydrukować go w then:
forEachAsync([1,2,3], returnSelf) .
  then(result => console.log(result);

Lub użyć mały wrapper asynchroniczny, aby poczekać na wynik, a następnie wydrukować:

(async function() { 
    console.log(await forEachAsync([1,2,3], returnSelf));
})();

Testowane przy użyciu

babel-node --experimental test.js
 6
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-29 05:50:03