ES6 Arrow Functions


Published: 2017-12-17
Updated: 2017-12-26
Web: http://fritzthecat-blog.blogspot.com/2017/12/es6-arrow-functions.html


ES6: ?

ES6 uses the term "arrow function" for what is called "lambda" in other programming languages. The idea is having an anonymous function that has no name, but could receive arguments, is able to return a value, and can use fields and functions of the surrounding environment (lexical scope). Related terms are "closure" and "continuation", they also use the lexical scope.

Here is an example of an ES6 lambda:

const numbers = [ 1, 2, 3, 4 ]
const evenNumbers = []
const oddNumbers = []

numbers.forEach((number) => {
  if (number % 2 === 0)
    evenNumbers.push(number)
  else
    oddNumbers.push(number)
})

This separates even from odd numbers. The Array.forEach() function expects a function as parameter, which is implemented as an arrow-function here. It has no name, the declared parameter (number) denotes the received array element. The => arrow points to the body, which can have different shapes. This one tests the parameter, and adds it to either the even or odd array. The forEach() function calls the nested arrow-function with each array-element.

Here is the same functionality implemented in JavaScript:

....

numbers.forEach(function(number) {
  if (number % 2 === 0)
    evenNumbers.push(number);
  else
    oddNumbers.push(number);
});

Not very much difference actually. The only difference is that an arrow-function refers to the "this" pointer of the environment (lexical scope) when it is inside a class or object. That makes it more intuitive compared to an anonymous JS function nested into another function, which does not know "this" any more. Read example "Handling of this" for more insight.

ES6 Arrow Function Tests

Click onto one of the buttons to get an example script into the text area. Below the script you find an explanation.

Description

Resume

Arrow functions (lambdas) are not so very different from anonymous JS functions, just accessing the "this" pointer has become more intuitive. Lambdas will be quite useful for small conversion tasks. But mind that they are anonymous, and thus not made to be reused, so they may promote code duplications!




This example shows the smallest possible arrow function. When there are no parameters to the function, the empty parentheses are required. The body of the function is "beep", nothing else. When there is just one statement in an arrow-function body, or the statements are wrapped into parentheses and separated by commas, the last statement's result is taken as return-value (see "Shapes of Lambdas" example). So the only thing this lambda does is returning "beep".

Mind that here the arrow-function is not anonymous, it was given a name explicitly, this is not a typical usage.

In second block you see the same functionality implemented in JavaScript.
It is useful in both languages to use semicolons, although I'm leaving it out in ES6 examples because this was recommended.

Array.map() generates a copy of its array. The function given as parameter to map() is executed for each member of the original array, and its return object is put into the new array. That's what lambdas are for: short conversions that don't need to be reusable or overridable.

The lambdas of this example increment a given number by 1, and thus we can generate an array of odd numbers from an array of even numbers. The example shows different ways to write such a function, all lambdas here do nearly the same.

We can leave out the parentheses around the parameter when there is just one parameter. The same applies to the function body, curly braces (or parentheses) are needed just when the body consists of more than one statement. Good style is to use curly braces and stating the return explicitly. When using parentheses and commas to wrap several statements inside, you must leave out the return in last statement.

There are two classes that both collect indexes of even and odd numbers into arrays called this.evenIndexes and this.oddIndexes. The first works with a lambda in forEach through the given array, the second uses a conventional function to do that.

Try to get rid of const that = this in WithFunction class. It is not possible, you would get "TypeError: this is undefined". You can access the "this" pointer from inside the function only by saving it to an outer variable, here called "that".

The same applies when using "this" in a function nested into an object method.

For conventional functions, the value of "this" is determined by how they are called. Arrow-functions have a lexical "this", the value being determined by the surrounding scope. This applies to keywords this and super, and also to arguments.


ɔ⃝ Fritz Ritzberger, 2017-12-17