
One of the most interesting parts of the new ECMAScript 6 standard is the arrow functions. Arrow functions, as the name implies, are defined by the new syntax that uses the arrow
=>
. However, besides the excellent syntax, the arrow functions differ from the traditional functions in other points:
- Lexical binding. The values ​​of the special variables this , super and arguments are not determined by how the arrow functions were called, but by how they were created.
- Unchangeable this , super and arguments . The values ​​of these variables inside the switch functions remain unchanged throughout the life cycle of the function.
- Arrow functions cannot be used as a constructor and throw an error when used with the new operator.
- Unavailability of the "own" value of the arguments variable.
There were several reasons for introducing these differences. The primary priority is that binding is used quite often in JavaScript. It is very easy to lose this desired value when using traditional functions, which can lead to unpredictable consequences. Another reason is that JS engines can easily optimize the execution of switch functions due to these limitations (as opposed to traditional functions that can be used as a constructor and that are free to modify
special variables ).
Note: This article is a compilation of a free translation of the article Understanding ECMAScript 6 arrow functions and readings of the latest draft specification (January 20, 2014 Draft Rev 22).Table of contents')
Syntax
In general, the syntax of the switch functions looks like this:
var fun = (x) => x;
It is very similar to similar syntax in languages ​​such as Scala, CoffeeScript, and the syntax of lambda expressions from C #.
The syntax of the switch functions may be different, depending on how you declare the function. A declaration always starts with a list of arguments, followed by an arrow and the function body. Both the argument list and the function body can have a different form, depending on what you are writing.
One parameter
Declaring a switch function that takes one argument and simply returns it looks very simple:
var reflect = value => value;
When the arrow function has only one argument, it can be declared without parentheses. The body of the function following the arrow may also be without curly brackets and may not contain the keyword
return .
Several parameters
But if you want to declare more than one parameter, you must frame the parameter list in parentheses:
var sum = (num1, num2) => num1 + num2;
The
sum
function simply sums two arguments. The only difference from the previous example is the presence of parentheses and a comma (just like in traditional functions).
No parameters
Similarly, a function without any arguments must have an empty parameter list enclosed in parentheses:
var sum = () => 1 + 2;
Traditional function body syntax
You can use the syntax of traditional functions for the body of the arrow function when it contains more than one expression. That is, wrap the function in braces and add the
return keyword:
var sum = (num1, num2) => { return num1 + num2; }
The body of the function will be processed in the same way as in the case of classical functions, except that the values ​​of the
special variables this ,
super and
arguments will be calculated differently.
Object literal
Separately, it should be mentioned that the body of the function which does not contain curly brackets and simply returns the object literal must be put into parentheses:
var getTempItem = id => ({ id: id, name: "Temp" });
Placing a literal object in parentheses indicates to the parser that curly braces are not the beginning of the traditional syntax for the function body, but the beginning of a literal.
Variable number of parameters
Since the “own” object of
arguments is not available inside the switch function (the value of
arguments is lexically related to the value of the
arguments of the traditional function within which the switch function was declared), then for switch functions with a variable number of parameters, use the
rest pattern from the restructuring
patterns . Example:
var getTempItems = (...rest) => rest;
Pattern restructuring as parameter
In this article, we are not looking at restructuring patterns — you can read about them in the article Review of ECMAScript 6, the next version of JavaScript , although this information is partially outdated.As can be seen from the previous example, despite the fact that the switch function has only one argument, it is still necessary to use parentheses when using the
destructuring patterns as the only parameter of the function. Examples with other
templates :
var a = ({a}) => a; var b = ([b]) => b;
Using arrow functions
Context setting
One of the common scripts in JavaScript is setting the correct value of
this inside a function (binding). Since the value of
this can be changed, then, depending on the context of the execution of the function, it is possible to mistakenly act on one object when you meant a completely different one. Look at the following example:
var pageHandler = { id: "123456" , init: function() { document.addEventListener("click", function(event) { this.doSomething(event.type);
In the above code, the
pageHandler
object must handle clicks on the page. The
init()
method hangs the handler on the desired event, which internally causes
this.doSomething()
. However, the code will not work properly. The reference to
this.doSomething()
not valid, since
this points to a
document
object inside an event handler instead of the intended
pageHandler
. When you try to execute this code, you will get an error, because the
document
object does not have a
doSomething
method.
You can set
this value on the
pageHandler
object using
handleEvent
or by calling the standard
bind()
method of the function:
var pageHandler = { id: "123456" , init: function() { document.addEventListener("click", (function(event) { this.doSomething(event.type);
Now the code works as intended, but it looks more cumbersome. In addition, calling
bind(this)
every time you create a new function, the value of which is tied to the
pageHandler
value, but the code works as you intended.
Arrow functions solve the problem in a more elegant way because they use the lexical binding of the value of
this (as well as
super and
arguments ) and its value is determined by the value of
this in the place where the arrow function was created. For example:
var pageHandler = { id: "123456" , init: function() { document.addEventListener("click", event => this.doSomething(event.type)); } , doSomething: function(type) { console.log("Handling " + type + " for " + this.id) } };
In this example, the handler is a pointer function in which
this.doSomething()
called. The value of
this will be the same as in the function
init()
, and the code in this example will work correctly, similar to the one used by
bind()
. Regardless of whether the call to
this.doSomething()
returns a value or not, the expression inside the body of the switch function does not need to be enclosed in braces.
In addition, the example above is also more efficient than calling
bind()
, because for the browser it is similar to the following code:
var pageHandler = { id: "123456" , init: function() { var self = this; document.addEventListener("click", function(event) { return self.doSomething(event.type) }); } , doSomething: function(type) { console.log("Handling " + type + " for " + this.id) } };
That is, the creation of a new function does not occur, as is the case with the
bind()
call.
Prokidyvanie context between multiple calls
Obviously, you can put one switch function into another, thereby “pushing” the value of
this through them:
var obj = { arr1: [1, 2, 3] , arr2: ['a', 'b', 'c'] , concatenate: function(a, b){ return a + "|" + b } , intersection: function() { return this.arr1.reduce( (sum, v1) =>
Use as argument
The short syntax of the switch functions makes them ideal candidates for passing as arguments to a call to other functions. For example, if you want to sort an array, you usually write something like this:
var result = values.sort(function(a, b) { return a - b });
Pretty verbose for a simple operation. Compare with a short recording of the switch function:
var result = values.sort((a, b) => a - b);
Using methods such as massive
sort()
,
map()
,
reduce()
and so on can be simplified using the short syntax of the arrow function.
Other features of the switch functions
Although the switch functions are different from the traditional functions, they have common features:
- The
typeof
operator returns "function"
for the arrow function - The arrow function is also an instance of the Function "class", so the
instanceof
will work the same way as with the traditional function - You can still use the
call()
, apply()
, and bind()
methods, but remember that they will not affect the value of this - You can use the
toMethod()
method, but it will not change the value of super ( the toMethod()
method is introduced in es6 and is not considered in this article ).
The essential difference from traditional functions is that an attempt to call an arrow function with an indication of the operator
new will cause an execution error.
Total
Arrow functions are one of the most interesting innovations in ECMAScript 6, which, having a short definition syntax, will simplify the transfer of functions as a parameter value to another function.
Laconic syntax allows you to write complex things.
even harder simpler. For example, the identifier generator will look like this (which looks
much more verbose on es5):
let idGen = (start = 0, id = start, reset = (newId = start) => id = newId, next = () => id++) => ({reset, next}); let gen = idGen(100); console.log(gen.next(), gen.next(), gen.reset(10), gen.next());
A lexical binding will close one of the biggest sources of pain and frustration for developers, as well as improve performance by optimizing at the level of the js-engine.

If you want to try the arrow functions, you can run the above examples in the Firefox console, which at the moment (02.2014 FF28) almost fully supports the arrow functions (FF28 doesn’t calculate the
arguments value correctly).
You can also try the switch functions and other es6 features in the Traceur
online translator .