DEV Community

Bruce Axtens
Bruce Axtens

Posted on • Updated on

Using Array prototypes in strange ways #2

Usually one uses .fill() to fill with a simple value. However, you can fill with other things, like records and even function references.

Here we pre-fill a 100 element array with random numbers:

const LIM = 1000;
const arrayOfRandomIntegers = new Array(LIM)
  .fill(function () {
    return Math.floor(Math.random() * LIM)
  })
  .map(function (item) {
    return item();
  });
Enter fullscreen mode Exit fullscreen mode

Granted, it's not quite as simple as a the value fill -- one still has to evaluate each of the function references in each of the cells -- however, it is another way of creating an array, and one which dispenses with obvious for(...;...;...) code.

The function reference approach allows for some interesting things. Below we preload a character array, first by filling with an object's method reference, and then with the function itself.

First the object itself:

function Generator(init) {
  var stuff,
  index;
  var that = this;
  if (init) {
    stuff = init;
    index = 0;
  }
  that.next = function () {
    return stuff.charAt(index++);
  }
  that.eod = function () {
    return index >= stuff.length;
  }
  return that;
}
Enter fullscreen mode Exit fullscreen mode

The example object exposes two methods: next() and eod() (end of data). When we instantiate the object we provide some data for it to work on. Every call to next() returns the next character. eod() is provided to check if we've run out of data. In this implementation the object will return an empty string if it does run out.

So, first instantiation and use:

const string = "lewd did i live - evil i did dwel";

const H = new Generator(string);
const arrayFromH = new Array(string.length)
  .fill(H.next)
  .map(function (item) {
    return item();
  });
Enter fullscreen mode Exit fullscreen mode

Here we fill with a reference to .next() and trust that the Generator object will fail politely if we ask for more data than it has to offer. As it is, because we've told Array only to allocate space for string.length, we're never going to find out if Generator is polite or otherwise.

Second go:

const G = new Generator(string);
const arrayFromG = new Array(string.length)
  .fill(G)
  .map(function (item) {
    return item.eod() ? "*" : item.next();
  });
Enter fullscreen mode Exit fullscreen mode

Here we store the reference to the function and then check with .eod() in the body of the .map(), storing an asterisk if we go too far.

By the way, the history of the "lewd ... dwel" thing can be found here

P.S. There are generators in ES6 and this isn't them.

Top comments (0)