(This was previously brought up in tc39/proposal-iterator-helpers#294, where the last comment suggested that the discussion be continued here.)
This function would join values produced by an iterator into a single string, like Array.prototype.join does for array-likes. Several other popular languages provide this feature, including Java, Kotlin, .NET and Python. Compare it to existing solutions in JS:
.toArray().join()has to collect all values into an intermediate array, which may use a lot of memory..reduce((acc, cur) => `${acc},${cur}`, "").slice(1)is quite verbose.
Below are preliminary spec text and a polyfill.
Iterator.prototype.join ( separator )
This method performs the following steps when called:
- Let O be the this value.
- If O is not an Object, throw a TypeError exception.
- Let iterated be the Iterator Record { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
- If separator is undefined, let sep be ",".
- Else,
- Let sep be Completion(ToString(separator)).
- IfAbruptCloseIterator(sep, iterated).
- Set iterated to ? GetIteratorDirect(O).
- Let result be the empty String.
- Let counter be 0.
- Repeat,
- Let value be ? IteratorStepValue(iterated).
- If value is DONE, return result.
- If counter > 0, set result to the string-concatenation of result and sep.
- If value is neither undefined nor null, then
- Let string be Completion(ToString(value)).
- IfAbruptCloseIterator(string, iterated).
- Set result to the string-concatenation of result and string.
- Set counter to counter + 1.
const { Object, Symbol, TypeError } = globalThis;
Object.defineProperty(Iterator.prototype, "join", {
value: {
join(separator) {
if (Object(this) !== this) {
throw new TypeError("Iterator.prototype.join called on non-object");
}
let sep = ",";
if (separator !== undefined) {
try {
sep = `${separator}`;
} catch (e) {
try {
this.return?.();
} catch {}
throw e;
}
}
let result = "";
let counter = 0;
for (const value of { [Symbol.iterator]: () => this }) {
if (counter > 0) {
result += sep;
}
if (value !== undefined && value !== null) {
result += `${value}`;
}
counter++;
}
return result;
},
}.join,
writable: true,
configurable: true,
});