wp-content/uploads/2016/01/PBS_Logo.png

In the previous instalment we started our redux and update of function objects in JavaScript. This fits into a larger mini-series within the larger series looking at all the different proverbial hats objects wear in JavaScript. The previous instalment was almost all redux, this one by contrast will be entirely dedicated to updated features added in ES6 that we’ve not seen before.

The instalment has a some-what strange structure because I felt it best to change my plans a little and extend the existing challenge by another week. Hopefully you won’t mind the slightly different flow of the sections compared to the norm.

You can download this instalment’s ZIP file here. If you prefer, you can access this instalment’s resources directly at the following links:

PBS 85 Challenge Update

It had been my intention to include the sample solution to the challenge set at the end of instalment 85 at the start of this instalment, and to end with a new challenge, but I’ve changed my mind on that. As I was working on my sample solution two things became clear to me — the challenge was a lot more difficult that I had intended, and, a good solution will rely heavily on jQuery, so it will make the perfect hook for a redux and update of our look at DOM objects and jQuery objects.

A Top-up for Extra Credit

If you’ve already completed the challenge and are very disappointed not to be getting any new ‘homework’, I offer a little top-up to this challenge for some proverbial extra credit.

If you can, add some extra UI to allow users to decide which currencies should be shown as the rows within the cards. Remember that each card represents a currency’s rate against a list of other currencies. So far those ‘other currencies’ have been hard-coded. The primary challenge is to simply add control over the cards, not to add control over the rows within the cards, so this literally adds an extra dimension to the problem.

Iterators

As you’ve probably noticed over these past few instalments, ES6 brought absolutely massive changes to JavaScript. Iterators are yet another new feature introduced to the language in ES6. We’ve actually already used iterators, but we’ve done so implicitly rather than explicitly.

Let’s start with the problem to be solved — it is often necessary to perform an action on a series of values, i.e., it is often necessary to iterate over a series of values. ES6 added the so-called iterator protocol to provide a standard mechanism for iteration. We won’t be going into the details here, but we do need to understand the official JavaScript terminology.

An object which can be iterated over can be said to be iterable. All JavaScript Arrays are iterable, as are JavaScript strings (one character at a time).

All iterables can produce an iterator object on demand.

Iterator objects provide a .next() function for iterating over the values represented by the iterator object. Each time you call .next() a dictionary (plain object) with two keys is returned — the first key is value, and will be the current value in the sequence, and the second key is done, a boolean indicating whether or not the end of the sequence has been reached.

Note that iterator objects are designed to be used once and then discarded, they are not intended as permanent references to the underlying data. When an iterator reaches the end of its sequence it is useless, there is no .previous() function, and there is no way to re-start the sequence!

As of ES6, a number of JavaScript objects are now iterable, including arrays, strings, and the special arguments objects within functions. Iterating over arrays and arguments seems obvious, but iterating over strings may seem a little stranger at first glance. The iterator objects produced from strings iterate over the string one character at a time. The developers of third-party libraries can also implement the iterator protocol, making their objects iterable too if they so desire. Modern versions of jQuery have added iterator support, so the objects returned from the $() function are now iterable, producing iterators that iterate one tag at a time.

Iterator Object Example

To play along with these examples, open a JavaScript console on the file pbs87a.html.

This all sounds very abstract, so let’s create an iterator object and interact with its .next() function. To do this we’ll use an array, and we’ll make use of the fact that as of ES6 the Array class/prototype provides a .values() function which returns a fresh iterator object representing the array’s current values.

Iterators and the for...of Loop

To date, when describing what the for...of loop does I’ve used vague language like for...of loops can iterate over arrays and for...of loops can iterate over array-like objects. We can now be exact! Both iterables and for...of loops were introduced in ES6, and that’s no coincidence — the truth is that for...of loops can iterate over any iterable.

While you can use .next() in a while loop to iterate over an iterable, in reality you’ll usually use for...of loops.

Let’s take a moment to look at for...of iterating over things other than arrays.

Firstly, we can use for...of to iterate over the special arguments variable that exists within all functions:

Now let’s iterate over a string:

Finally, let’s demonstrate iterating over a jQuery object. The file pbs87a.html contains an un-ordered list with the ID jq_iter_demo that contains 3 list items. We can iterate over it like so:

We need to break this very short snippet down to understand it.

The first thing to note is that the iterator objects created by jQuery iterate over native DOM objects, not jQuery objects. This is consistent with how callbacks work in jQuery, so while people may quibble with that choice, it is at least consistent. This means that to treat each iterated value as a jQuery object we have to pass it to the $() function. In the example I chose to name the values produced by the iterator li, but before I can call jQuery’s .addClass() function I have to convert it from a native DOM object to a native DOM object with $(li).

Note that '#jq_iter_demo li' is a CSS selector that selects all <li> tags within an element with the id jq_iter_demo.

Finally, also note the use of jQuery function chaining to first remove all classes with .removeClass(), and then add in the randomly chosen class.

This is a very contrived example, but it does show how you use for...of loops with jQuery, and it’s all thanks to iterators 🙂

Generator Functions

Iterable objects are very useful for storing ordered data, but there are more things you may wish to iterate over than stored data. You may wish to iterate over a series of results from some kind of calculation. This is where so-called generator functions come in.

Generator functions can be used to create so-called generator objects, and those generator objects are iterable. As well as being iterable, generator objects also have a directly accessible .next() function so there is no need for an extra step to get from an iterable to an iterator object (i.e. no equivalent to myArray.values()). In effect, a generator object does triple-duty as a generator object, an iterable, and an iterator object.

In practice, generator functions are used to create generator objects, and their values are iterated over using .next() or for...of loops.

If it helps, you can think of generator functions as iterator object factories.

Creating Generator Functions with * and yield

Before we look at the exact syntax for creating a generator function, we need to explain a new concept — resumable functions.

So far in everything we’ve seen throughout this series, functions are black boxes that take an arbitrary amount of arguments, execute a sequence of instructions in order, optionally return a single value, and end. They are completely linear, and once a function starts executing it continues until it finishes.

Generator functions are difference! They still take arbitrarily many arguments, they are still executed in order, and they can still return a single value if desired, but they can also pause execution at any time by yielding a value. Yielding is very similar to returning except that it doesn’t end the function, instead, it pauses it. A yield can emit a value, like return does, but it can also receive new arguments when execution resumes. A generator function’s scope is not destroyed when it yields, so when execution resumes all local variables will be just as they were when the function yielded.

The keyword yield is used to yield values from and to a generator function.

Generator functions are special functions, so you create them using a special syntax. The idea is similar to how async functions are defined, but a little different, instead of a keyword like async, generator functions are pre-fixed with the * character.

You can create generator functions using function statements like so:

You can also create generator functions using function literals like so:

Note that you can use loops within generator functions, and, that it is perfectly acceptable to have a generator function with an intentional infinite loop that will keep yielding values for ever. Such infinite generator functions will yield, but not return.

Using Generator Functions

Generator functions are called to create generator objects, and those objects are then interacted with to step through a sequence of values.

Let’s consider the very simple sample generator included in pbs85a.html:

This function yields two strings, then returns a string.

To use this generator function we first call it to create a generator object and store it in the global variable myGeneratorObj, then call .next() on that generator object.

The first thing to note here is that creating the generator object does not execute the generator object. Nothing gets logged until the first time we call .next() on the generator object.

The second thing to note is that when a value is yielded done is false, but when a value is returned, done is true.

Calling generators directly can be useful, but you can also iterate over all their values with a for...of loop. Because generator objects are also iterator objects they can be used directly within a for...if loop, but there is a caveat, for...of loops only iterate over yielded values, they ignore returned values:

So, there are two things of note here. Firstly, the for...of loop automatically unpacks the dictionaries actually returned by .next(), so val contains the actual value yielded. And secondly, only the yielded values are included in the loop, the returned value is ignored. I honestly have no idea what it works like this, but it does!

Generator Function Arguments

Generator functions can accept arguments in the same way any other functions can.

Let’s illustrate this by looking at a more practical example that is designed to play nice with for...of loops. Our generator will produce a series of random numbers of a requested length. The number of random numbers desired will be passed as the first argument to the generator function. You’ll find this function defined in pbs87a.html, but I’m including the full code below:

Note that the function only uses yield, and does not use return. This is to ensure for...of loops see all the random numbers.

We can now use this generator like so:

There is of course no need to create a separate variable, so we can collapse this down down like so:

Infinite Generators

Our examples so far have all been finite series of values, but in reality many series go on for ever.

While infinite series make no sense in a for...of loop, they can be very useful in other contexts, particularly interactive contexts where a user can keep performing an action as often as they like.

To illustrate this point let’s look at a more real-world random number generator. Again, this function is defined in pbs87a.html, but included below for convenience.

This better random number generator will be able to provider either a finite or infinite number of random numbers, depending on how it’s called. If called with no arguments it will produce an infinite stream, if called with a number as the first argument it will produce that many random numbers.

This improved generator can still be used within for...of loops to generate finite series:

But it can now also be used with .next() to generate infinite series:

To make this example a little more real-world, pbs87a.html contains a web UI for generating random numbers using this generator. The HTML markup is quite straight forward:

This is basically just a Bootstap card containing a bootstrap form consisting of a button to generate a random number, and a text box to show it. The key points to note are that the button has the ID rng_btn, and the text box has the ID rng_tb.

This UI is brought to life in the document ready handler by creating an infinite RNG generator object and adding a click handler to the button:

As you can see, the code to bring this form to life is very short. The key things to note are that rngObj.next().value will always evaluate to the next random number, and the jQuery .val() and .select() functions are used to set the content of the text box and then select. The reason I chose to select the newly generated number is to make it easier for users to copy-and-paste the number somewhere.

Passing Values Back to yield

I mentioned previously that yield can receive as well as emit values. This might seem like a strange concept at first — return is very much a one-way street after all! But, since the yield keyword is used to pause and resume the function, it does actually make sense. When yield triggers a pause can emit a value, and when execution is resumed it can receive a value.

The data flow to and from yield statements is handled by the .next() function.

I like to think of the yield keyword and the .next() function as two end of a wormhole — when you yield a value it gets returned by .next(), and when you pass a value to .next() it gets emitted by yield.

This might all sound a little confusing, so let’s look at a practical example. We can use a generator function to implement an accumulator — a counter that can be incremented by an arbitrary amount, and can be asked for its current value at any time.

Again, you’ll find the code in pbs87a.html, but I’m also including it here:

The important thing to note here is the use of the value potentially emitted by yield:

The value to the right of the yield keyword will be returned by .next(), and the yield operation will evaluate to value passed to .next(). In this case that means that the value passed to .next() will get stored in the variable incBy.

To use this generator function we first create a generator object with it, and we can then read out the current value by calling .next() with no arguments, and update the value by calling .next() with a number as the only argument.

Because a generator function does not even start to execute until the first time .next() is called, the first call .next() cannot be connected to a yield statement, so, any value passed to it will vanish into the ether. For this reason we need to prime the pump on our accumulator by calling .next() once after we create it:

As with the random number generator example, it’s easy to build a simple UI for an accumulator using jQuery and Bootstrap. You’ll find such a UI in pbs87a.html.

The markup for the form is very simple:

As you can see, it’s a Bootstrap card with an input group consisting of a text box and a submit button, a text box, and a reset button. The two text boxes have IDs so their values can be read and written, and the form as a whole has an ID so its submit and reset events can be reacted to.

The code to bring this basic UI to life is entirely contained within the document ready handler, and is quite short:

This code creates a variable to store the generator object for accumulator, then adds submit and reset event handlers to the form, and triggers a reset event to get everything initialised properly.

The reset event handler simply creates and stores a new accumulator and calls .next() on it once to get it ready to accept values.

The submit event handler simply reads the value from the input text box (defaulting to 0), then passes it to .next() and stores the result in a variable named newTotal. It then simply writes newTotal to the output text box.

The only other thing to note is the use of function chaining to add the two event handlers and to trigger the event in a single statement.

Final Example/Optional Challenge

You can choose to treat this final example as an example, or, to treat it like a challenge and attempt to create your own solution before opening pbs87b.html to see my implementation.

Infinite generator functions are extremely well suited to user-driven sequences of arbitrary length like the famous Fibonacci series.

The first two numbers in the sequence are 0 and 1, and from then on the next number in the sequence is the result of adding the two previous numbers together.

The example/challenge implements the Fibonacci series as a generator function, and creates a simple UI for it using Bootstrap and jQuery.

Since it is effectively a spoiler for those who want to treat this example as a challenge, my sample solution is included below the final thoughts.

Final Thoughts

We’ve now re-visited all the various kinds of functions we’d met before thought this series, and, learned about the new generator functions ES6 brought to the language. That wraps up our redux and update on function objects. In the next instalment we’ll re-visit DOM and jQuery objects, and we’ll use my sample solution to the challenge set at the end of instalment 85 as the hook for that. In the following instalments we’ll continue to look at the different hats objects can wear in JavaScript, focusing on strings and then regular expressions.

Final Example/Bonus Challenge Solution (Spoilers 🙂)

You can see my sample solution in action here.

In my solution I chose to make use of Bootstrap, jQuery, Mustache, and Numeral.js to build a solution that works well and a looks good but has only a small amount of quite straightforward and understandable code.

Before looking at the UI, let’s look at the implementation of the Fibonacci series itself:

The comments hopefully make it clear how this function implements the Fibonacci algorithm. Notice that we yield the initial two values which the algorithm hard-codes before we start the infinite loop that then continues to apply the algorithm for ever.

We can use this function from the console like so:

With the generator working we’re ready to build a UI around it.

I chose to use a Bootstrap card to contain the UI as a nice little widget. I chose to have two buttons — one to generate the next value, and one to re-set the UI back to the start of the series. Between the two buttons I added a paragraph into which each number will be appended. Because this is a series I thought it was important to retain a running history of previous values rather than having a single number change each time the button is pushed.

Given those requirements I came up with the following markup for the UI:

Note that I gave the form the ID fib_fm to facilitate access via jQuery to attach submit and reset handlers later.

Once I had a basic solution working it became clear that there was a need to highlight the current value, so I chose to do that by making the most recent number larger than the others, and different in colour. I used Bootstrap’s primary colour for the current value, and secondary for all the others. To highlight the numbers I rendered them as Bootstrap badges, and to make the current number bigger I wrapped it in a span with the class h4.

Since there would be lots of numbers to render, I chose to create a Mustache template for rendering one number. Because I only needed this one template, and because it is a very small template, I chose to embed it right into the document using a <script> tag:

To facilitate access via jQuery I gave the badge two additional classes of my own choosing — fib_val & fib_val_current.

With the markup and template taken care of, the final piece of the puzzle is the event handlers to bring the UI to life. All of the code to do this is contained within a jQuery document ready event handler.

First, I declared some variables in the document ready event handler’s scope to facilitate the event handlers themselves:

Next, I added reset and submit handlers to the form, and triggered the reset handler to initialise the UI. I used function chaining to collapse this down into one multi-line statement:

Hopefully the comments are sufficient to make the code self-documenting.

One thing I do want to draw attention to though is the code for un-highlighting the previous value:

The difference between the highlighted current value and the un-highlighted previous values is three-fold. Firstly, the current value has the class badge-primary while the previous values have badge-secondary instead. Secondly, the current value has the additional class fib_val_current. And finally, the current value is wrapped in a <span> with the class h4 that the other value are not wrapped in.

Firstly, the $() function is passed a CSS selector that looks for any tag with both the classes fib_val and fib_val_current, and confines it’s search within the output area (stored in $fibOut).

The un-needed classes are then removed using jQuery’s .removeClass() function, and the needed additional class added with jQuery’s .addClass() function.

That leaves just the un-wanted wrapping of the value in the span with the class h4. I wasn’t sure how best to do this so I googled for “unwrap tag with jQuery”, and was immediately led to the documentation for jQuery’s .unwrap() function. This function does exactly what’s needed, so it was literally as simple as adding .unwrap() into the function chain.