Skip to content

Instantly share code, notes, and snippets.

@leobalter
Last active July 25, 2019 22:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leobalter/092fc36adccfcc86e8e7b074817078e1 to your computer and use it in GitHub Desktop.
Save leobalter/092fc36adccfcc86e8e7b074817078e1 to your computer and use it in GitHub Desktop.
// Motivation: we need a reverse iterator for list objects.
// For Arrays, only reduceRight or decrementing loops
// Currently impossible in Map/Set without a full loop or storing the list into an Array
// Goal: a iterator that allows looping through the elements of a list from the last to the first element. Similar to .values()
// Goal: it should not change the original array
// Goal: it should allow interrupting the iteration.
// Question: Should add equivalents to keys and entries?
// Question: Names for the methods?
Symbol.reverse = Symbol('reverseIterator');
function *reverse() {
if (!this || typeof this !== 'object') {
throw new TypeError('this is not an Object');
}
const arr = this;
let { length } = arr;
while (length) {
length = --length;
if (!Object.prototype.hasOwnProperty.call(arr, length)) {
continue;
}
yield arr[length];
// Dynamically jump to the last item in the array if it's shorter
if (arr.length < length) {
length = arr.length; // .next will jump to the latest existing value
}
}
}
Array.prototype[Symbol.reverse] = reverse;
var array1 = [1, 2, 3, 4, 5];
console.log([...array1[Symbol.reverse]()]); // [5, 4, 3, 2, 1];
var obj = {
length: 7,
6: 'a',
get 5() { this.length = 1; return 'b'; },
4: 'z',
1: 'z',
0: 'c'
};
console.log([...Array.prototype[Symbol.reverse].call(obj)]); // [ 'a', 'b', 'c']
var array2 = [1,,2,,,3];
console.log([...array2[Symbol.reverse]()]); // [ 3, 2, 1 ]
/* ------------------- */
// As methods:
Array.prototype.reverseIterator = Array.prototype[Symbol.reverse]; // Needs bikesheding on the name!!!
// Map and Set not drafted here
Map.prototype.reverse = Map.prototype[Symbol.reverse];
Set.prototype.reverse = Set.prototype[Symbol.reverse];
@ljharb
Copy link

ljharb commented Jul 25, 2019

There is no requirement in the process document for it appearing specifically in any place including the readme; it does say "prose" which means we should indeed document things in writing somewhere, but it seemed a bit obvious since there's tons of usage in the wild of patterns like [...x].reverse() etc, so I don't think it occurred (to me at least) that it would be necessary to spell it out.

Now that it's stage 1, we will of course create a proper proposal repo and document it the conventional way.

(worth noting that this gist also ended up linking to https://github.com/leebyron/ecmascript-reverse-iterable as well which has much more motivation documented)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment