Blog

Ideas and insights from our team

JavaScript's Lambda and Arrow Functions


alt text

Lambda expressions are present in most of modern programming languages (Python, Ruby, Java...). They are simply expressions that create functions. This is really important for a programming language to support first-class functions which basically means passing functions as arguments to other functions or assigning them to variables.

In JavaScript pre-ES6 we have function expressions which give us an anonymous function (a function without a name).

var anon = function (a, b) { return a + b };

In ES6 we have arrow functions with a more flexible syntax that has some bonus features and gotchas.

// we could write the above example as:
var anon = (a, b) => a + b;
// or
var anon = (a, b) => { return a + b };
// if we only have one parameter we can loose the parentheses
var anon = a => a;
// and without parameters
var () => {} // noop

// this looks pretty nice when you change something like:
[1,2,3,4].filter(function (value) {return value % 2 === 0});
// to:
[1,2,3,4].filter(value => value % 2 === 0);

One of the major advantages of arrow functions is that it does not have it's own this value. It's this is lexically bound to the enclosing scope. This mean we can kiss goodbye to this horrible pattern:

class Logger {
  dumpData(data) {
    var _this = this;

    // this dumps data to a file and get the name of the file via a callback
    dump(data, function (outputFile) {
      _this.latestLog = outputFile;
    });
  }
}
// using arrow functions
class Logger {
  dumpData(data) {
    dump(data, outputFile => this.latestLog = outputFile);
  }
}

However there are some gotchas you should be aware of:

  • This should be pretty obvious, but because this is lexically bound you can't change it; call() and apply() will not be able to provide another value for this.
  • There is no arguments variable:
  (function () {console.log(arguments)})(1, 2); // will output [1, 2]
  (() => console.log(arguments))(1, 2); // will raise ReferenceError: arguments is not defined
  • Be careful when returning object literals
  (() => {foo: 1})() // this will return undefined. 'foo: 1' is interpreted as a statement composed of a label and the literal 1
  // the correct way should be wrapping it with parenthesis
  (() => ({foo: 1}))() // returns Object {foo: 1}

Remember this is all ES6 and not supported by all browsers but you can always use Babel.

About André Ericson

Frontend and Backend developer, Python and modern JavaScript evangelist. CLI is my /home/.

Comments