Learning ES6: Generators as Iterators

electric-generator

I feel like all the articles in the Learning ES6 series have been leading up to generators. They really are the feature most JavaScript developers are excited about in ECMAScript 6. They very well may be the future of asynchronous programming in JavaScript. That’s definitely something to get excited about!

Generators can be used both as data producers and data consumers. In this post, we’re going to look at how generator functions are a much more convenient way to produce data and and create iterators. It’s the simpler way to use generators. In the last article we covered iterators & iterables, so you may need to familiarize yourself with that before looking at generators as iterators.

TL;DR

A generator function is a special type of function that when invoked automatically generates a special iterator, called a generator object. Generator functions are indicated by function* and make use of the yield operator to indicate the value to return for each successive call to .next() on the generator.

function* range(start, count) {
    for (let delta = 0; delta < count; delta++) {
        yield start + delta;
    }
}

for (let teenageYear of range(13, 7)) {
    console.log(`Teenage angst @ ${teenageYear}!`);
}

Feel free to clone the Learning ES6 Github repo and take a look at the generators code examples page showing them off in greater detail.

With out further ado, let’s keep reading.

Continue reading “Learning ES6: Generators as Iterators”

Learning ES6: Iterators & iterables

iterators-gonna-iterate

We’ve talked about promises and new collection APIs, so now we’re finally going to talk about iterators & iterables. They’ve come up in passing in the last couple of posts, so it’s about time we talk about them deeply.

TL;DR

Iterators provide a simple way to return a (potentially unbounded) sequence of values. The @@iterator symbol is used to define default iterators for objects, making them an iterable.

Continue reading “Learning ES6: Iterators & iterables”

Learning ES6: New Collections

collections

Let’s continue focusing on the new functionality introduced with ES6 in the Learning ES6 series. The main focus in the next few articles will be all about asynchronous programming. We’ll ultimately talk about generators, but there are a few building blocks we need to get through first. The new collections we’ll talk about now aren’t really building blocks for generators, but I feel that they are important to learn. In addition, they are types of iterables which we’ll deep dive into in the next article.

TL;DR

ES6 introduces four new efficient collection data structures to mitigate our ab-use of object and array literals.

Continue reading “Learning ES6: New Collections”

Learning ES6: Promises

Pinky Swear

Like clockwork the Learning ES6 series continues on, looking at promises. It will be the first feature we’ve looked at in this series that really is more than syntactic sugar. But promises aren’t entirely new to JavaScript. They’ve existed for quite some time in helper libraries. ECMAScript 6 now brings native promise support to JavaScript via the Promise API. Let’s jump right in!

TL;DR

A promise represents the eventual result of an asynchronous operation. Instead of registering a callback in the call to an async function, the function returns a promise. The caller registers callbacks with the promise to receive either a promise’s eventual value from the async operation or the reason why the promise cannot be fulfilled.

// Creating a promise wrapper for setTimeout
function wait(delay = 0) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, delay);
    });
}

// Using a promise
wait(3000)
    .then(() => {
        console.log('3 seconds have passed!');
        return wait(2000);
    })
    .then(() => {
    	console.log('5 seconds have passed!');
    	x++; // ReferenceError triggers `catch`
    })
    .catch(error => {
    	// output: ReferenceError
    	console.log(error);
    })
    .then(() => {
    	// simulate `finally` clause
    	console.log('clean up');
    });

Did you notice the use of default parameters and arrow functions too? If you’re unfamiliar with those ES6 features, you should check out the articles detailing how they work. Interested in learning more about ES6 promises? Clone the Learning ES6 Github repo and take a look at the promises code examples page showing off the features in greater detail.

Well you’ve come this far. You might as well keep going!

Continue reading “Learning ES6: Promises”

Learning ES6: Classes

classes

We’re going from enhanced object literals that look a lot like classes to actual classes in ES6. We’ll learn, however, that these aren’t really classes, but syntactic sugar over the existing prototype functions in JavaScript. Let’s continue on with the Learning ES6 series series!

TL;DR

ECMAScript 6 provides syntactic sugar over the prototype-based, object-oriented pattern in JavaScript. ES6 classes provide support for constructors, instance and static methods, (prototype-based) inheritance, and super calls. Instance and static properties are not (yet) supported.

// Define base Note class
class Note {
	constructor(id, content, owner) {
		this._id = id;
		this._content = content;
		this._owner = owner;
	}

	static add(...properties) {
		// `this` will be the class on which
		// `add()` was called increment counter
		++this._idCounter;

		let id = `note${this._idCounter}`;

		// construct a new instance of the note passing in the
		// arguments after the ID. This is so subclasses can
		// get all of the arguments needed
		let note = new this(id, ...properties);

		// add note to the lookup by ID
		this._noteLookup[id] = note;

		return note;
	}

	static get(id) {
		return this._noteLookup[id];
	}

	// read-only
	get id() { return this._id; }

	get content() { return this._content; }
	set content(value) { this._content = value; }

	get owner() { return this._owner; }
	set owner(value) { this._owner = value; }

	toString() {
		return `ID: ${this._id}
			Content: ${this._content}
			Owner: ${this._owner}`;
	}
}

// Static "private" properties (not yet supported in class syntax)
Note._idCounter = -1;
Note._noteLookup = {};

class ColorNote extends Note {
	constructor(id, content, owner, color='#ff0000') {
		// super constructor must be called first!
		super(id, content, owner);
		this._color = color;
	}

	get color() { return this._color; }
	set color(value) { this._color = value; }

	toString() {  // computed method names are supported
		// Override `toString()`, but call parent/super version
		// first
		return `${super.toString()}
			Color: ${this._color}`;
	}
}

// `add` factory method is defined on `Note`, but accessible
// on ColorNote subclass
let colorNote = ColorNote.add('My note', 'benmvp', '#0000ff');

// output: ID: note0
// Content: My Note
// Owner: benmvp
// Color: #0000ff
console.log(`${colorNote}`);

// output: true
console.log(Note.get('note0') === colorNote);

This is just a quick example of how ES6 classes work. Be sure to clone the Learning ES6 Github repo and take a look at the classes code examples page showing off the features in greater detail.

The example also uses default parameters, rest parameters, and the spread operator so you may want to revisit the relevant articles if you’re not familiar. It also makes use of template strings for string interpolation, so you should read up on that as well.

Continue reading “Learning ES6: Classes”

Learning ES6: Enhanced Object Literals

object_literal

Wow, we’re making some good progress covering ECMAScript 6 features in this Learning ES6 series series. We most recently covered template literals and arrow functions. Now we zero in on the enhancements to object literals, another piece of ES6 syntactic sugar.

TL;DR

ECMAScript 6 makes declaring object literals even more succinct by providing shorthand syntax for initializing properties from variables and defining function methods. It also enables the ability to have computed property keys in an object literal definition.

function getCar(make, model, value) {
	return {
		// with property value shorthand
		// syntax, you can omit the property
		// value if key matches variable
		// name
		make,  // same as make: make
		model, // same as model: model
		value, // same as value: value

		// computed values now work with
		// object literals
		['make' + make]: true,

		// Method definition shorthand syntax
		// omits `function` keyword & colon
		depreciate() {
			this.value -= 2500;
		}
	};
}

let car = getCar('Kia', 'Sorento', 40000);

// output: {
//     make: 'Kia',
//     model:'Sorento',
//     value: 40000,
//     depreciate: function()
// }
console.log(car);

car.depreciate();

// output: 37500
console.log(car.value);

The enhanced object literals code examples page has many more examples showing off each feature in more detail. There are also some ES6 katas for testing your ES6 enhanced object literal knowledge.

Continue on for more details!

Continue reading “Learning ES6: Enhanced Object Literals”

Learning ES6: Arrow Functions

right arrow sign

So far in the Learning ES6 series, we’ve looked at block scoping, default parameters, destructuring, rest & spread operators, for-of operator, and template literals. Today let’s continue the series to learn about arrow functions, a.k.a. “fat arrow” functions.

TL;DR

Arrow functions are more or less a shorthand form of anonymous function expressions that already exist in JavaScript. In ES6 this looks like:

let squares = [1, 2, 3].map(x => x * x);

Is equivalent to this in ES5:

var squares = [1, 2, 3].map(function (x) {
	return x * x;
});

As you can see a lot of the verbosity of old-style function expressions is removed and what’s left is the fat arrow (=>) joining the two main ingredients of the function: the arguments and function body.

You’ll find the greatest utility in arrow functions in places where functions take an anonymous callback function, like event handlers (such as onClick, $.ajax, etc.) and array processors (such as map, sort, etc.)

Interested in learning about arrow functions in more detail? Feel free to check out the arrow functions code examples page, which shows off the features in great detail. You can also try your hand at ES6 katas to see how much you’ve really learned.

Let’s keep going!

Continue reading “Learning ES6: Arrow Functions”

Learning ES6: Template literals & tagged templates

template literals

Template literals and tagged templates are our 6th topic in the Learning ES6 series. If you’re new to the series, we most recently covered for-of loops and destructuring.

Template literals, as well as tagged templates, are still primarily syntactic sugar, so you can totally do them in ES5. In fact, we have been doing them in ES5 up to this point. But the amount of code needed to mimic these ES6 features in ES5, especially tagged templates, can be pretty substantial.

TL;DR

ES6 template literals are a brand new type of string literal, delimited by backticks (`), that natively support string interpolation (token substitution) and multi-line strings. And because they use backticks as a delimiter, they can include single and double quotes without needing to escape them.

Continue reading “Learning ES6: Template literals & tagged templates”

Learning ES6: Destructuring

After learning all about default parameters and rest & spread operators, let’s continue the syntactic sugar train in our Learning ES6 series with destructuring in ECMAScript 6.

TL;DR

Destructuring makes it easier to work with objects and arrays in JavaScript. Using a pattern syntax similar to object and array literals, we can poke into data structures and pick out the information we want into variables.

// object pattern matching
let {lName, fName} = {fName: 'John', age: 15, lName: 'Doe'};

// array pattern matching
let [first, second, third] = [8, 4, 100, -5, 20];

// output: Doe, John
console.log(lName + ', '+ fName);

// output: 100, 4, 8
console.log(third, second, first);

As you can see, we can store properties of an object or elements of an array using pattern matching. You can find many more examples in the destructuring code examples which are part of the Learning ES6 Github repo.

If you’re finding destructuring intriguing (or maybe confusing), keep on reading for a more in-depth explanation.

Continue reading “Learning ES6: Destructuring”

Learning ES6: Rest & Spread Operators

Let’s continue the Learning ES6 series and look at the new rest and spread operators introduced in ECMAScript 6 and how they can make our code both cleaner and clearer. We’ve already talked about default parameters and block-scoping, so play catch-up if you need to!

TL;DR

The ES6 rest operator is three dots (...) preceding a function header parameter and should be able to completely replace the need for the problematic arguments special variable:

function join(separator, ...values) {
	return values.join(separator);
}

// all of the parameters after the first
// are gathered together into `values`
// which is a true `Array`
// output: "one//two//three"
console.log(join('//', 'one', 'two', 'three'));

And we should no longer need the apply function with the new ES6 spread operator, three dots (...) preceding a function call argument:

function volume(width, length, height) {
	return width * length * height;
};

// the array values are separated into
// separate parameters
// output: 80 (2 * 8 * 5)
console.log(volume(...[2, 8, 5]));

These quick examples are only scratching the surface of how to use the rest and spread operators. Be sure to check out the full suite of parameter handling code examples (a part of the Learning ES6 Github repo) and keep reading.

Continue reading “Learning ES6: Rest & Spread Operators”