
Research
/Security News
Fake imToken Chrome Extension Steals Seed Phrases via Phishing Redirects
Mixed-script homoglyphs and a lookalike domain mimic imToken’s import flow to capture mnemonics and private keys.
js-xiterable
Advanced tools
Make ES6 Iterators Functional Again
Suppose we have a generator like this.
function* count(n) {
let i = 0;
while (i < n) yield i++;
};
We make it more functional like this.
import {Xiterable} from './xiterable.js';
const xcount = new Xiterable(n => count(n));
const tens = xcount(10);
const odds = tens.filter(v=>v%2).map(v=>v*v);
const zips = tens.zip(odds);
[...tens]; // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[...odds]; // [ 1, 9, 25, 49, 81]
[...zips]; // [[0, 1], [1, 9], [2, 25], [3, 49], [4, 81]]
In other words, this module make any iterables work like Array, with .map, .filter and so on.
npm install js-xiterable
locally
import {
Xiterable,
xiterable, zip, zipWith, xrange, repeat
} from './xiterable.js';
remotely
import {Xiterable} from 'https://cdn.jsdelivr.net/npm/js-xiterable@0.1.3/xiterable.min.js';
% node -r esm
Welcome to Node.js v14.5.0.
Type ".help" for more information.
> import * as $X from 'js-xiterable'
undefined
> $X
[Module] {
Xiterable: [Function: Xiterable],
isIterable: [Function: isIterable],
repeat: [Function: repeat],
version: '0.0.3',
xiterable: [Function: xiterable],
xrange: [Function: xrange],
zip: [Function: zip],
zipWith: [Function: zipWith]
}
> [...$X.xrange().take(10).filter(v=>v%2).map(v=>v*v)]
[ 1, 9, 25, 49, 81 ]
>
from any built-in iterables...
new Xiterable([0,1,2,3]);
new Xiterable('0123');
new Xiterable(new Uint8Array([0,1,2,3]))
or your custom generator (with no argument)...
let it = new Xiterable(function *() {
let i = 0;
for (;;) yield i++;
});
[...it.take(8)]; // [ 0, 1, 2, 3, 4, 5, 6, 7]
Generators are treated as an infinite iterable. But you can override it by giving its length for the 2nd argument and the implentation of nth for the 3rd argument. see .nth() and .map() for more example.
let it = new Xiterable(function *() {
let i = 0;
for (;;) yield i++;
}, Number.POSIVE_INFINITY, n => n);
it.nth(42); // 42
it.take(42).reversed().nth(0) // 41
A factory function is also exported as xiterable.
import {xiterable as $x} from 'js-xiterable';
$x('01234567').zip('abcdefgh').map(v=>v.join('')).toArray(); /* [
'0a', '1b', '2c', '3d', '4e', '5f', '6g', '7h'
] */
.toArray()Returns [...this].
.nth().nth(n) returns the nth element of this if the original itertor has .nth or Array-like (can access nth element via [n]. In which case nth() is auto-generated).
Unlike [n], .nth(n) accepts BigInt and negatives.
let it = xiterable('javascript');
it.nth(0); // 'j'
it.nth(0n); // 'j'
it.nth(9); // 't'
it.nth(-1); // 't'
it.nth(-1n); // 't'
it.nth(-10); // 'j'
It raises exceptions on infinite (and indefinite) iterables
it = xiterable(function*(){ for(;;) yield 42 }); // infinite
[...it.take(42)]; // Array(42).fill(42)
it.nth(0); // throws TypeError;
it = xiterable('javascript');
it = it.filter(v=>!new Set('aeiou').has(v)); // indefinite
[...it]; // ['j', 'v', 's', 'c', 'r', 'p', 't']
it.nth(0); // throws TypeError;
BigInt is sometimes necessary when you deal with large -- combinatorially large -- iterables like js-combinatorics handles.
import * as $C from 'js-combinatorics';
let it = xiterable(new $C.Permutation('abcdefghijklmnopqrstuvwxyz'));
it = it.map(v=>v.join(''));
it.nth(0); // 'abcdefghijklmnopqrstuvwxyz'
it.nth(-1); // 'zyxwvutsrqponmlkjihgfedcba'
it.nth(403291461126605635583999999n) === it.nth(-1); // true
.lengthThe (maximum) number of elements in the iterable. For infinite (or indefinite iterables like the result of .filter()) Number.POSITIVE_INFINITY is set.
it = xiterable('javascript');
it.length; // 10
it = it.filter(v=>!new Set('aeiou').has(v));
it.length; // Number.POSITIVE_INFINITY
[...it].length; // 7
The number can be BigInt for very large iterable.
it = xiterable(new $C.Permutation('abcdefghijklmnopqrstuvwxyz'));
it.lenth; // 403291461126605635584000000n
You can tell if the iterable is infinite or indefinite via .isEndless.
it = xiterable('javascript');
it.isEndless; // false
it = it.filter(v=>!new Set('aeiou').has(v));
it.isEndless; // true
it = xiterable(new $C.Permutation('abcdefghijklmnopqrstuvwxyz'));
it.isEndless; // false
it = xiterable(function*(){ for(;;) yield 42 });
it.isEndless; // true
.map().map(fn, thisArg?) works just like Array.prototype.map except:
.map of this module works with infinite iterables.
if this is finite with working .nth, the resulting iterable is also reversible with .reversed and random-accissible via .nth.
it = xiterable(function*(){ let i = 0; for(;;) yield i++ });
[...it.map(v=>v*v).take(8)] // [0, 1, 4, 9, 16, 25, 36, 49]
it.nth(42); // throws TypeError
it = xiterable(it.seed, it.length, n=>n); // installs nth
it.nth(42); // 41
.filter().filter(fn, thisArg?) works just like Array.prototype.filter except:
.filter of this module works with infinite iterables.
unlike .map() the resulting iterable is always marked infinite because there is no way to know its length lazily, that is, prior to iteration. See .length for example
.take().take(n) returns an iterator that takes first n elements of this.
.drop().drop(n) returns the iterator that drops first n elements of this.
.zip().zip(...args) zips iterators in the args. Static version also available.
[...Xiterable.xrange().zip('abcd')] // [[0,"a"],[1,"b"],[2,"c"],[3,"d"]]
.reversedreturns an iterator that returns elements in reverse order. this must be finite and random-accesible via .nth() or exception is thrown.
Array.prototypeThe following methods in Array.prototype are supported as follows. For any method meth, [...iter.meth(arg)] deeply equals to [...iter].meth(arg).
| method | available? | Comment |
|---|---|---|
| concat | ✔︎ | |
| copyWithin | ❌ | mutating |
| entries | ✔︎ | |
| every | ✔︎ | |
| fill | ❌ | mutating ; see repeat |
| filter | ✔︎ | see filter |
| find | ✔︎ | |
| findIndex | ✔︎ | |
| flat | ✔︎ | |
| flatMap | ✔︎ | |
| forEach | ✔︎ | |
| includes | ✔︎* | * throws RangeError on infinite iterables if the 2nd arg is negative |
| indexOf | ✔︎* | * throws RangeError on infinite iterables if the 2nd arg is negative |
| join | ✔︎ | |
| keys | ✔︎ | |
| lastIndexOf | ✔︎* | * throws RangeError on infinite iterables if the 2nd arg is negative |
| map | ✔︎ | see map |
| pop | ❌ | mutating |
| push | ❌ | mutating |
| reduce | ✔︎* | * throws RangeError on infinite iterables |
| reduceRight | ✔︎* | * throws RangeError on infinite iterables |
| reverse | ❌ | mutating. See reversed |
| shift | ❌ | mutating |
| slice | ✔︎* | * throws RangeError on infinite iterables if any of the args is negative |
| some | ✔︎ | |
| sort | ❌ | mutating |
| splice | ❌ | mutating |
| unshift | ❌ | mutating |
| filter | ✔︎ |
Mutating functions (functions that change this) are deliberately made unavailable. e.g. pop, push…
Functions that need toiterate backwards do not work on infinite iterables. e.g. lastIndexOf(), reduceRight()…
They are also exported so you can:
import {repeat,xrange,zip,zipWith} from 'xiterable.js'
Examples below assumes
import {Xiterable} from 'xiterable.js'.
Examples below assumes
Xiterable.zipZips iterators in the argument.
[...Xiterable.zip('0123', 'abcd')] // [[0,"a"],[1,"b"],[2,"c"],[3,"d"]]
Xiterable.zipWithZips iterators and then feed it to the function.
[...Xiterable.zipWith((a,b)=>a+b, 'bcdfg', 'aeiou')] // ["ba","ce","di","fo","gu"]
Xiterable.xrangexrange() as Python 2 (or range() of Python 3).
for (const i of Xiterable.xrange()){ // infinite stream of 0, 1, ...
console.log(i)
}
[...Xiterable.xrange(4)] // [0, 1, 2, 3]
[...Xiterable.xrange(1,5)] // [1, 2, 3, 4]
[...Xiterable.xrange(1,5,2)] // [1, 3]
Xiterable.repeatReturns an iterator with all elements are the same.
for (const i of Xiterable.repeat('spam')) { // infinite stream of 'spam'
console.log(i)
}
[...Xiterable.repeat('spam', 4)] // ['spam', 'spam', 'spam', 'spam']
FAQs
Make ES6 Iterators Functional Again
The npm package js-xiterable receives a total of 12 weekly downloads. As such, js-xiterable popularity was classified as not popular.
We found that js-xiterable demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Mixed-script homoglyphs and a lookalike domain mimic imToken’s import flow to capture mnemonics and private keys.

Security News
Latio’s 2026 report recognizes Socket as a Supply Chain Innovator and highlights our work in 0-day malware detection, SCA, and auto-patching.

Company News
Join Socket for live demos, rooftop happy hours, and one-on-one meetings during BSidesSF and RSA 2026 in San Francisco.