More With Arrow Functions in ES6

Monday, January 5, 2015 by K. Scott Allen

In a previous post we took a first look at arrow functions in ES6. This post will demonstrate another feature of arrow functions, as well as some additional scenarios where you might find arrow functions to be useful.

Every JavaScript programmer knows that the this pointer is a bit slippery. Consider the code in the following class, particularly the code inside of doWork.

class Person {
    constructor(name) {
        this.name = name;
    }

    doWork(callback) {
        setTimeout(function() {
            callback(this.name);
        }, 15); 
    }
}

The anonymous function the doWork method passes into setTimeout will execute in a different context than doWork itself, which means the this reference will change. When the anonymous function passes this.name to a callback, this won’t point to a person object and the following test will fail.

var person = new Person("Scott");
person.doWork(function(result) {
    expect(result).toBe("Scott"); // fail!
    done();
});

Since developers can never rely on JavaScript’s this reference when asynchronous code and callbacks are in the mix, a common practice is to capture the value of this in a local variable and use the local variable in place of this. It’s common to see the local variable with the name self, or me, or that.

doWork(callback) {
    var self = this;
    setTimeout(function() {
        callback(self.name);
    }, 15); 
}

The above code will pass, thanks to self capturing the this reference.

If we use an arrow function in doWork, we no longer need to capture the this reference!

doWork(callback) {
    setTimeout(() => callback(this.name), 15); 
}

The previous test will pass with the above code in place because an arrow function will automatically capture the value of this from its outer, parent function. In other words, the value of this inside an arrow function will always be the same as the value of this in the arrow’s enclosing function. There is no more need to use self or that, and you can nest arrow functions arbitrarily deep to preserve this through a series of asynchronous operations.

Using Arrow Functions Everyday

If you embrace the arrow function syntax, you might find yourself using the syntax with every few lines of code you write. JavaScript’s affinity for asynchronous operations has created an enormous number of APIs requiring callback functions. However, as JavaScript is a solid functional programming language, more and more synchronous APIs have also appeared with function arguments.

For example, ES5 introduced forEach and map methods on array objects.

let result = [1,2,3,4].map(n => n * 2);
expect(result).toEqual([2,4,6,8]);

let sum = 0;
[1,2,3,4].forEach(n => sum += n);
expect(sum).toBe(10);

There are also many libraries like underscore and lodash that use higher order functions to implement filtering, sorting, and grouping of data. With ES5 the code looks like the following.

let characters = [
    { name: "barney", age: 36, blocked: false },
    { name: "fred", age: 40, blocked: true },
    { name: "pebbles", age: 1, blocked: false }
];

let result = _.find(characters, function(character) {
    return character.age < 40;
});

With arrow functions, the result calculation becomes more expressive.

let result = _.find(characters, character => character.age < 40);
expect(result.name).toBe("barney");

You can even write a Jasmine test using an arrow function.

it("can work with Jasmine", () => {
    var numbers = [1,3,4];
    expect(numbers.length).toBe(3);
});

Many of the examples shown in this section, like the examples using forEach, map, and _, all work with the concept of collections. Other feature of ES6, like iterators, will make working with collections noticeably more flexible and reliable. We’ll turn out attention to iterators next.

Arrow Function In ES6

Tuesday, December 9, 2014 by K. Scott Allen

JavaScript has always been a functional programming language. You can pass functions as arguments to other functions, and invoke a function that returns a function back to you. The ES6 standard improves JavaScript’s functional programming capabilities by offering a new, succinct syntax for creating functions. In addition, ES6 defines new syntax to offer features closely associated with functional programming, features like iterators and lazy evaluation. Let’s start looking at the new capabilities by looking at the arrow function, which will look familiar to anyone who has worked with CoffeeScript or C# code.

An arrow function doesn’t require the function keyword, or curly braces, or a return statement. However, arrow functions do require a new operator, the =>, which looks like an arrow pointing to the right and which gives these expressions their name. To build an arrow function for adding two numbers, one simply has to write the following.

let add = (x,y) => x + y; 

On the left-hand side of the arrow is the parameter list for the function. In this example there are two parameters, x and y. To the right of the arrow is the executable code. In this case, the code returns the sum of x and y. You could think of the arrow as pointing the parameters to the code that uses them.

Invoking an arrow function looks no different than invoking a traditional function.

let result = add(3, 5); 

expect(result).toBe(8);

Arrow functions that use exactly one function parameter do not need to surround the parameter with parenthesis.

let square = x => x * x; 

If an arrow function requires zero parameters, or more than one parameter, then the parenthesis are required.

let add = (x,y) => x + y;             // required parens 
let square = x => x * x;              // optional parens 
let compute = () => square(add(5,3)); // required parens 
let result = compute(); 

expect(result).toBe(64); 

So far, the examples use a single expression to the right of the arrow operator. When using a single expression, curly braces and return statements are not required. The return value of the function will be the value of the expression.

However, an arrow function may contain a more complex block of statements, but this approach does require braces and an explicit return (if the function wants to return a value).

let add = (x,y) => {
    var result = x + y;
    return result;
};

In the next post of this series, we’ll look at a special quality of arrow functions, and also see how we can use them in some common scenarios.

Class Inheritance in ECMAScript 6

Tuesday, November 25, 2014 by K. Scott Allen

Continuing from a previous post

Over the years, there have been various approaches to building class hierarchies in JavaScript. All these approaches worked by stitching together constructor functions and prototype objects and each approach was slightly different from the others.

The ES6 standard allows for a declarative, consistent approach to inheritance using the class and extends keywords. As an example, let’s start with a simple class to represent a person with a name.

class Person {
    
    get name() {
        return this._name;
    } 

    set name(newName){
        if(newName){
            this._name = newName;
        }
    } 

}

var p1 = new Person();
p1.name = "Scott";
expect(p1.name).toBe("Scott");

Now we also need a class to represent an employee who has both a name and a title. Using the extends keyword, we can have an Employee class inherit from the Person class, meaning every object instantiated as an Employee will also have all the methods and properties available for a Person.

class Employee extends Person {

    get title() {
        return this._title;
    }

    set title(newTitle) {
        this._title = newTitle;
    }
}

var e1 = new Employee();
e1.name = "Scott"; // inherited from Person
e1.title = "Developer";

expect(e1.name).toBe("Scott");
expect(e1.title).toBe("Developer");
expect(e1 instanceof Employee).toBe(true);
expect(e1 instanceof Person).toBe(true);

When describing the relationship between Employee and Person we often say Person is a super class of Employee, while Employee is a sub class of Person. We can also say that every employee is a person, and as you can see in the above code, the instanceof check in JavaScript confirms that an object created using the Employee class is also an instance of Person.

While every Employee object will inherit all the state and behavior of a Person, the Employee class also has the ability to override the methods and properties defined by Person. For this example, let’s add a doWork method to every Person.

class Person {

    get name() {
        return this._name;
    }

    set name(newName){
        if(newName){
            this._name = newName;
        } 
    }

    doWork() {
        return this.name + " works for free";
    } 

}

var p1 = new Person();
p1.name = "Scott";
expect(p1.doWork()).toBe("Scott works for free");

By default, an Employee will behave the same as a Person.

var e1 = new Employee();
e1.name = "Scott";
e1.title = "Developer";
expect(e1.doWork()).toBe("Scott works for free");

However, in the Employee class we can override the behavior of doWork by providing a new implementation.

class Employee extends Person {

    // ...

    doWork() {
        return this.name + " works for a salary";
    }
}

var p1 = new Person();
p1.name = "Scott";
expect(p1.doWork()).toBe("Scott works for free");

var e1 = new Employee();
e1.name = "Scott";
e1.title = "Developer";
expect(e1.doWork()).toBe("Scott works for a salary");

Now, as the tests prove, objects instantiated from the Employee class will behave slightly differently in the doWork method than objects instantiated from the Person class. In object-oriented programming, we call this behavior polymorphism.

Using Super

There are times when a class will want to invoke behavior in its super class directly, which can be done with the super keyword. For example, the Employee class could implement the doWork method as follows.

doWork() {
    return super() + "!";
}

Invoking super will execute the super class method of the same name, so with the above code a passing test would now look like the following.

var e1 = new Employee();
e1.name = "Alex";
e1.title = "Developer";

expect(e1.doWork()).toBe("Alex works for free!");

A class can also refer explicitly to any method in the super class.

doWork() {
    return super.doWork() + "!";
}

Super Constructors

One common scenario for using super is when inheriting from a class that requires constructor parameters. The following Person class now accepts a name parameter during initialization.

class Person {

    constructor(name) {
        this._name = name;
    }

    get name() {
        return this._name;
    }

}

Now an employee will need both a title and a name during initialization.

class Employee extends Person {

    constructor(name, title) {
        super(name);
        this._title = title;
    }

    get title() {
        return this._title;
    }

}

Notice how the Employee constructor method uses super to pass along the name parameter to the Person constructor and reuse the logic inside the super class. What’s interesting about JavaScript compared to other object oriented languages, is how you can choose if and when to call the super class constructor. If I were to pick a style to remain consistent, I’d always make a call to super in a sub class before executing any other logic inside the constructor. This style would keep JavaScript classes consistent with the behavior of other object-oriented languages.

The Caveat

Now that we know what inheritance looks like in ES6, it’s time for a word of caution. Inheritance is a fragile technique to achieve re-use that only works well in a limited number of scenarios. Do a search for “composition over inheritance” to see more details.

Adventures in Angular Podcast and an AngularJS Oslo Meetup

Tuesday, November 18, 2014 by K. Scott Allen

Last month I did an interview with the Adventures in Angular podcast crew, you can listen here.

I also did a talk at the AngularJS Meetup in Oslo. You can watch the recoding here.

Both the podcast and the Meetup talks were loosely centered around using the next version of JavaScript with the current version of Angular.

In addition to all the syntax sugar in ES6, which makes JavaScript code more expressive, the new class keyword works well for building services and controllers in Angular. As an example, imagine you are building a Pong game, and need a service to control the left paddle and a second service for the right paddle. One paddle is controlled by the keyboard, the other by AI. This is a scenario where you might, if you are brave, consider inheritance, as long as the relationship stays simple.

(function(app) {

    class Paddle {
        constructor() {
            this.x = 0;
            this.y = 0;
        }

        startMoveDown() {
            this.y += 2;
        }

        stopMoveDown() {
            this.y -= 1;
        }

        startMoveUp() {
            this.y -= 2;
        }

        stopMoveUp() {
            this.y += 1;
        }
    }

    class LeftPaddle extends Paddle {
        constructor(keyboardHandler) {
            Paddle.call(this);
            this.x = 25;
            this.y = 100;
            keyboardHandler.onArrowUp(38, () => this.startMoveUp(), this.stopMoveUp());
            keyboardHandler.onArrowDown(40, () => this.startMoveDown(), this.stopMoveDown());
        }
    }

    class RightPaddle extends Paddle {
        constructor() {
            Paddle.call(this);
            this.x = 975;
            this.y = 300;
        }
    }

    app.service("leftPaddle", LeftPaddle);
    app.service("rightPaddle", RightPaddle);

}(angular.module("pong")));

The class constructor for controllers and services will be injectable, but you’ll want to use module.service to register service classes, and not module.factory, because only .service instantiates the service using new.

Thoughts on Angular 2.0

Thursday, November 13, 2014 by K. Scott Allen

The Great Wave off KanagawaNeil Young once sang how “every wave is new until it breaks”. The line was a poke at trendiness in the music industry, but I find the lyrical snippet is applicable to software development, too, in a number of subtle ways.

There has been a lot of turmoil surrounding the future direction of Angular, which is fair. The preview and announcements made for Angular 2.0 during ng-europe were dramatic and conveyed no empathy for the customers and development teams who have taken a dependency on the framework. Those people are left wondering when the ng-wave will break.

The Blessings and Curses of Backwards Compatibility

Web developers have always faced incompatibilities, but have also been fortunate enough to build software on top of a set of technologies and standards that have diligently preserved backward compatibility. This diligence allows the nearly 20 year old web page for the animated movie Space Jam to live on. We’ve been accustomed to building software using web standards that keep working into the future. Stability is good for business.

But backward compatibility has a price. I believe the web moves at a snails pace, which is contrary to popular opinion. However, compare the evolution of the JavaScript language to some of its peers like C# or even Java. Next year’s ECMASCript 6 release is the first big move forward for the language in nearly 20 years. Also consider the XMLHttpRequest API. The API is central to today’s applications, but it has taken the industry 15 years to standardize the API  and build the tools to make mainstream developers productive with asynchronous requests and dynamic DOM updates.

Should Angular 2.0 be backward compatible? Or should Angular 2.0 follow Py3k?

Python 3.0, also known as “Python 3000” or “Py3K”, is the first ever intentionally backwards incompatible Python release. There are more changes than in a typical release, and more that are important for all Python users. Nevertheless, after digesting the changes, you’ll find that Python really hasn’t changed all that much – by and large, we’re mostly fixing well-known annoyances and warts, and removing a lot of old cruft.

Surfing the Waves of Change

Web development feels like a fast changing environment, but a closer look will show we mostly churn in the turbulence of small, incremental improvements. It’s rare for a wave to arrive and move everyone forward.

I still believe Angular 1.x is the best wave to ride today. I already have applications in production with Angular 1.2, and at least one more on the way with 1.3.  With the core Angular code base being only 25k lines of JSDoc’ed, tested, working, healthy code, I believe the wave can keep can keep rolling for years to come.

I also believe Angular 2.0 should be a new wave that makes a break from Angular 1.x and evolves without being encumbered by backward compatibility or designs for an easy migration path. We’re still early in the history of application development on the web, and there will one day be a newer, bigger, better swell. It’s name might be Angular 2, or maybe something entirely new will come along. That’s life in the rough seas of web development, where you can either fight the waves and drown, or surf the waves and stay on top.

Constructor Functions and Controllers in AngularJS

Wednesday, November 12, 2014 by K. Scott Allen

AngularJSThere are a few points in “AngularJS: The Bad Parts” I’d be happy to debate, but let’s focus on “Bad Idea #4”, talking about controller constructor functions:

That’s right, these constructors never create new instances. They are “applied” to a scope object.

Let’s use the following example. A simple controller that is setup to use controller as syntax from the view.

var module = angular.module("app", []);

var MainController = function() {
      
    this.message = "Hello";
    
    this.changeMessage = function() {
        this.message = "Bonjour!";
    };

    this.isMainController = function(object) {
        return object instanceof MainController;
    };

    this.isObject = function(object) {
        return object instanceof Object;
    };

};

module.controller("MainController", MainController);

If we place the following markup in a view:

<div>
    {{ main.isMainController(main) }}
    {{ main.isObject(main) }}
</div>

.. we’ll see the output true and true. The first true is a good indication that Angular does use the controller function as a constructor function, in other words, Angular invokes the function using the new keyword. In fact, we can even rewrite a controller using the everyday constructor function and prototype object approach of JavaScript, and everything just works.

var MainController = function() {
    this.message = "Hello";         
};

MainController.prototype = {
       
   changeMessage: function() {
       this.message = "Bonjour!";
   },

   isMainController: function(object) {
       return object instanceof MainController;
   },

   isObject: function(object) {
       return object instanceof Object;
   }

};

The above is actually a good example of why I like working with Angular. You can write plain, simple JavaScript objects using established conventions and terminology, then plug the objects into Angular to achieve a goal. There is no magic required or intrusions from the framework. You can even start writing controllers using ES 6 class syntax, but that’s a topic for a future post.

Features of ES6 Part 10: Behind The Class

Tuesday, November 11, 2014 by K. Scott Allen

In a previous post we looked at the new class keyword in JavaScript.

We’ve always had the ability to create objects in JavaScript, and give these objects data to hold and methods to call. In fact, we could have written an “employee” object using a simple object literal instead of a class.

let developer = { 
    name: "Scott", 
    doWork: function() { 
        return `${this._name} is working`; 
    }, 

    get name() { 
        return this._name.toUpperCase(); 
    }, 

    set name(newName) { 
        if(newName) { 
            this._name = newName; 
        } 
    } 

}; 

expect(developer.name).toBe("SCOTT"); 

developer.name = "Alex"; 
expect(developer.doWork()).toBe("Alex is working");

The advantage to having a class is how we can create multiple developers just by using the new keyword and not have to write out an entire literal definition like the above code. Each object is unique and contains its own data, but the method implementations are consistent and shared.

let dev1 = new Employee("Scott"); 
let dev2 = new Employee("Alex");

In fact, even before the class keyword came along, we had the ability to define a blueprint for object construction in JavaScript. The approach was one we called the “constructor function and prototype object” approach.

let Employee = function(name) { 
    this._name = name; 
}; 

Employee.prototype = { 

    doWork: function() { 
        return `${this._name} is working`; 
    }, 

    get name() { 
        return this._name.toUpperCase(); 
    }, 

    set name(newName) { 
        if(newName) { 
            this._name = newName; 
        } 
    } 
}; 

let developer = new Employee("Scott"); 
expect(developer.name).toBe("SCOTT");

As it turns out, all the class keyword is doing behind the scenes is setting up a constructor function and prototype object. This means all of the tricks we’ve learned in the past still work. For example, “borrowing” a method from a prototype object:

class A { 

    doWork() { 
        return "complete!"; 
    } 

} 

var result = A.prototype.doWork.call(); 
expect(result).toBe("complete!");

The instanceof operator also works as expected.

class A { 
    // … 
} 

var a = new A(); 

expect(a instanceof A).toBe(true); 
expect(a instanceof Object).toBe(true);

You can also still augment all instances of a type by modifying prototype objects (if you like to live dangerously).

class A { 

} 

A.prototype.newMethod = function() { 
    return "new!"; 
}; 

var a = new A(); 
expect(a.newMethod()).toBe("new!");

You can think of the class keyword as being syntactic sugar for creating constructor functions and prototype objects. However, there is more to the class keyword than what we’ve seen so far. We’ll look at class inheritance in the next post.

My Pluralsight Courses

K.Scott Allen OdeToCode by K. Scott Allen
What JavaScript Developers Should Know About ECMAScript 2015
The Podcast!