Js arrow functions. About the JavaScript “this” keyword: features of use with explanations. Rules for using arrow functions

They have become very fashionable, we see them in all new articles. And, if you are not used to them, you will have a hard time understanding modern (ES6) code containing arrow functions.

This article is not intended to tell you when or how to use them. I'll just try to explain the new syntax for those who are seeing it for the first time. Whether you use it or not is not important, but sooner or later you will still encounter it somewhere. So it's better to understand the mechanics of this new syntax.

Here's a small example:

Const addOne = function(n) ( return n + 1; )

The above code can be written like this:

Const addOne = (n) => ( return n + 1; )

Or, in this case, even shorter:

Const addOne = (n) => n + 1;

The second example uses ( ... ) curly braces, but since it is only one line of code, the curly braces can be omitted and the return is implied, as seen in the third example.

One parameter

When an arrow function has one parameter, the parentheses can be omitted:

// Was: someCallBack((results) => ( ... )) // Now: someCallBack(results => ( ... ))

But, if there are no parameters, you must use opening and closing parentheses:

SomeCallBack(() => ( ... ))

Callback functions

Function arrows are especially useful for callbacks. Those familiar with JavaScript are familiar with its lexical scope, which is pretty neat, but can do tricks like this ( this):

Var_this = this; someCallBack(function() ( _this.accessOuterScope(); ))

There are several variations of this "_this" (such as "self" or "that"), but the idea is the same. In callback functions we need access to the outer scope version, but the idea is the same. In callback functions, we need access to the outer scope's version of this , which is now different from before since we're talking about a callback function.

By using arrow functions, we get "block scope" and "this", which is the same "this" in both cases. This means that the code above can be rewritten without _this = this:

SomeCallBack(() => ( this.accessOuterScope(); ))

"Wrapper"

Let's imagine a situation like in React, where the event onClick should call doSomething() , (), but should also pass arguments to doSomething() (eg ID). This example doesn't actually work:

Some user) ))

The code will run, but technically it will call doSomething() immediately when the page loads. To solve this problem, some developers refer to a wrapper function:

Const User = React.createClass(function() ( render: function() ( return Some user), onClick: function() ( doSomething(this.props.userId); ) ))

The absence of a parenthesis in this.onClick means that it is simply a function reference rather than a function call.

The onClick() function is now something of a wrapper for doSomething() . With arrow functions you can make “wrappers” of this type:

Const User = React.createClass(function() ( render: function() ( return doSomething(this.props.userId))>Some user ) ))

As an alternative, we could also use .bind() , which doesn't require any wrappers (arrow functions or anything):

Const User = React.createClass(function() ( render: function() ( return Some user ) ))

Browser support for arrow functions

If you need browser support other than latest versions Chrome And Firefox, use Babel transpiler to convert the ES6 code you wrote to ES5.

ES6 has a new way to create functions - Using the Arrow => operator. Such functions are called arrow functions. They offer a more compact syntax. They don't have a name and they work differently with this .

The first thing we will do is run a Babel script that will monitor the files and create fresh versions when they change.

Open the project folder in command line(KS). Enter the command:

And press Enter

In the src folder we will create a file arr.js and immediately indicate it in the index.html file

</script>

The latest versions of browsers support arrow functions without transpilation and my browser is one of them.

Let's write a function that adds two numbers and returns their sum. Let's call the function add .

Function add (x, y) ( return x + y; ) console.log (add (3, 6));

In the console we will see the result - 9

Now, let's convert this function to an arrow function.

Let's remove the word function , remove the function name and remove the curly braces, and the word - return . After the parameters we will put an arrow.

Let add = (x, y) => x + y; console.log(add(4, 6));

If you look at the type of the add variable using the typeof operator:

Console.log(typeof(add));

This is what we will see in the function console

This means that arrow functions are ordinary functions. And you can verify this by looking at the transpiled code.

"use strict"; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) ( return typeof obj; ) : function (obj) ( return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj ; ); var add = function add(x, y) ( return x + y; ); console.log(add(4, 6)); console.log(typeof add === "undefined" ? "undefined" : _typeof(add));

We can see that Babel has turned our code into a simple function expression.

Let's write a simple function that will square a given number.

Let add = (x, y) => x + y; console.log(add(4, 6)); console.log(typeof(add)); let square = function(a) ( return a * a; ) console.log(square (4));

Let's look in the console:

The arrow function will look like this:

Let square = x => x * x;

If an arrow function only takes one parameter, then there is no need to enclose it in parentheses!

Let's write a function that takes no parameters at all.

Function givNumer () ( return 33; ) console.log(givNumer ());

This function simply prints the number 33 to the console. Arrow:

Let givNumer = () => 33; console.log(givNumer());

Let's create a function that will not return anything. It will simply display a message in the browser console.

Let log = function () ( console.log("Hello World!"); ); log();

Switch:

Let log = () => console.log("Hello World!!!"); log();

Let's create a function whose body will consist of two lines.

The function will take two parameters. Let's create a variable in the body of the function. After that we will return the result.

Let mult = function (a, b) ( let result = a * b; return result; ) console.log(mult (4, 5));

If there are several lines in an arrow function, then curly braces - () are required! And be sure to define what this function returns using the return keyword

Switch:

Let mult = (a, b) => ( let result = a * b; return result; ) console.log(mult (4, 5));

Now let's create a function that returns an object literal:

Let literal = function () ( return ( name: "John"); ) console.log (literal ());

In the console we will see:

Now let's try to create an arrow function that will return an object literal.

It should be remembered that if an arrow function returns an object literal, then parentheses are needed - ()

Arrow function returning an object literal:

Let literal = () => ((name: "John")); console.log(literal());

Now let's try to use the arrow function as an IIFE - Immediately-invoked function expression

In short, this is a function that is executed immediately after the declaration

It looks like this:

(function () ( console.log("IIFE"); ))();

The arrow IIFE function will look like this:

(() => console.log("IIFE"))();

An important feature of arrow functions is that the arrow must come immediately after the parameters!

You can’t just take it and move it down to a line below. It will give an error!

Practical application of arrow functions. Arrow functions are very convenient to use with arrays.

Let's create an array with some numbers and call it numbers . I think you know that arrays have useful methods that allow you to iterate through the array, filter it, etc.

Let's calculate the sum of all array variables. To do this, I will declare another variable - let sum = 0;

Let's use the forEach() method that every array has, we will iterate over the elements and add to the sum.

Let numbers = ; let sum = 0; numbers.forEach(function(num) ( sum += num; )); console.log(sum);

In the console we will see 55. Let's turn this function into an arrow function: numbers.forEach(num => sum += num); console.log(sum);

Thus, what previously took us three lines now takes one.

We can also square each element of the array.

Let squared = numbers.map(n => n * n); console.log(squared);

Arrow functions and this . To do this, I will create an object literal that I will save in the person variable.

The person object will have a name property with the value 'Bob' and a greet property with the value 'Greet'. We'll print the greeting to the console and also look at the purpose of this .

Let person = ( name: "Bob", greet: function () ( console.log("Hello! My name is " + this.name); console.log(this); ) ); person.greet();

In the browser console we will see the greeting and the person object itself.

Now we'll replace the function with an arrow and see what happens to this .

Let person = ( name: "Bob", greet: () => ( console.log("Hello! My name is " + this.name); console.log(this); ) ); person.greet();

Now we didn't get the value of the name and the value of this is window !

But why? The point is that the value of this is taken from the context in which the function is declared. ! No matter where this function will be performed. This can be seen in the picture:

We have a program.

So far there is nothing in it except the window object. Added a person object. Notice that we use an arrow function for the method. As we said, the value of this will be taken from the context. Context is the environment. In this case, the environment of the person object, all its properties and methods, will be window object. And if the value of this is taken from the context, then this will refer to the window object.

If we look at a regular function, then we know that this refers to the person object itself. You may ask why the value of this in arrow functions is taken from the context? And the answer is very simple - they did it that way! :-) The point is that arrow functions were created to solve problems in a different situation. Let's look at an example. To see the problem we will return to our arrow function.

Let person = ( name: "Bob", greet: function () ( console.log("Hello! My name is " + this.name); console.log(this); ) );

Let's imagine that our Bob is quite busy and needs a couple of seconds to complete his work. Wait 2 seconds. we simulate using the setTimeout() function; .This function takes a function as the first parameter and the number of milliseconds to wait as the second parameter.

Let person = ( name: "Bob", greet: function () ( setTimeout(function () ( console.log("Hello! My name is " + this.name); console.log(this); ), 2000) ; ) ); person.greet();

If you have experience with JavaScript, then I think you understand what the problem is. Anyway, let's look at what will happen in the browser. Exactly two seconds later we will see this picture in the browser.

But why? If you look at our code, it is logical to assume. that this refers to the person object since we are using a regular function. The thing is that setTimeout() belongs to the window object. If you write it like this: window.setTimeout() , then what do you think thus refers to? And in the console we will get the same result! There are several ways to solve this problem in ES5. We'll look at the most common one: Before setTimeout(), I'll declare another variable that and assign this as the value. And now, in the body of the function, instead of this, we will indicate that.

Let person = ( name: "Bob", greet: function () ( let that = this; setTimeout(function () ( console.log("Hello! My name is " + that.name); console.log(that) ; ), 2000); ) ); person.greet();

Now, thanks to the closure, the function we send to setTimeout() will have access to the variable that, the value of which will be this , that is, in this case, the person object.

For clarity, you can look at what our that and this refer to.

Let person = ( name: "Bob", greet: function () ( let that = this; setTimeout(function () ( console.log("Hello! My name is " + that.name); console.log("It is my That = " + that); console.log("It is my This = " + this); ), 2000); ) ); person.greet();

We will see confirmation in the console:

We see that this will be the window object - This = , and that will be our person object - That = .

In ES6, we can simply use an arrow function to solve this problem.

Let person = ( name: "Bob", greet: function () ( setTimeout(() => ( console.log("Hello! My name is " + this.name); console.log("It is my This = " + this); ), 2000); ) ); person.greet();

As a result, we will see in the console:

IN graphic example for an arrow function, the context will be a person object, not a window object. that's why this will refer to person .

In addition to compact syntax, arrow functions were introduced to solve problems such as these.

For reference, you can see how Babel solved this

Var person = ( name: "Bob", greet: function greet() ( var _this = this; setTimeout(function () ( console.log("Hello! My name is " + _this.name); console.log(" It is my This = " + _this); ), 2000); ) ); person.greet(); Babel used the same method that we used in ES5. The only difference is that we called the variable that, and Babel called it - _this. Thanks to the closure, the function we send to setTimeout will have access to the _this variable and, as a result, to the person object.

I think the hardest part of this part is understanding how closures work.

Some more features of arrow functions:
You can see more information on ES6 and arrow functions in my post

Hi all! In this article, we'll look at what arrow functions are in ES6 and how to use them.

Arrow functions are functions that are written using the arrow operator (=>).

Let's look at an example right away:

Let add = (x, y) => x + y;
console.log(add(5, 2));

As a result of executing this function, we will see the number 7 in the console.

First, we pass the arguments in parentheses, then we put the arrow sign, and then we write the code of the function itself. In our case, it simply takes two numbers and adds them. In theory, this is the same as function expression in ES5. If you are using Babel or similar compilers, they will most likely write something like this:

Var add = function add(x, y) (
return x + y;
};

If your function takes only one parameter, the parentheses are optional.

Let square = x => x*x;

This function takes only one argument and squares the given number.

Function without parameters:

Let func = () => 77;

If your function contains several lines, then, firstly, you need to use curly braces, and secondly, be sure to write what the function returns, i.e. use the return keyword.

Let multiply = (x, y) => (
let result = x*y;
return result;
};

If you need to return an object literal, then you need to wrap it in parentheses:

Let getObject = () => (( brand: "BMW" ));

The self-invoking function looks like this:

An arrow function expression is a syntactically compact alternative to a regular function expression , although without its own bindings to the this , arguments , super , or new.target keywords. Arrow function expressions are ill suited as methods, and they cannot be used as constructors.

Syntax Basic syntax (param1, param2, …, paramN) => ( statements ) (param1, param2, …, paramN) => expression // equivalent to: => ( return expression; ) // Parentheses are optional when there"s only one parameter name: (singleParam) => ( statements ) singleParam => ( statements ) // The parameter list for a function with no parameters should be written with a pair of parentheses. () => ( statements ) Advanced syntax // Parenthesize the body of a function to return an object literal expression: params => ((foo: bar)) // Rest parameters and default parameters are supported (param1, param2, ...rest) => ( statements ) (param1 = defaultValue1, param2, …, paramN = defaultValueN) => ( statements ) // Destructuring within the parameter list is also supported var f = ( = , (x: c) = (x: a + b)) => a + b + c; f(); // 6 Description

Two factors influenced the introduction of arrow functions: the need for shorter functions and the behavior of the this keyword.

Shorter functions var elements = [ "Hydrogen", "Helium", "Lithium", "Beryllium" ]; // This statement returns the array: elements.map (function(element) ( return element.length; )); // The regular function above can be written as the arrow function below elements.map((element) => ( return element.length; )); // // When there is only one parameter, we can remove the surrounding parentheses elements.map (element => ( return element.length; )); // // When the only statement in an arrow function is `return`, we can remove `return` and remove // ​​the surrounding curly brackets elements.map(element => element.length); // // In this case, because we only need the length property, we can use destructuring parameter: // Notice that the `length` corresponds to the property we want to get whereas the // obviously non-special `lengthFooBArX` is just the name of a variable which can be changed // to any valid variable name you want elements.map ((( length:lengthFooBArX )) => lengthFooBArX); // // This destructuring parameter assignment can also be written as seen below. However, note that in // this example we are not assigning `length` value to the made up property. Instead, the literal name // itself of the variable `length` is used as the property we want to retrieve from the object. elements.map ((( length )) => length); // No separate this

Before arrow functions, every new function defined its own this value based on how the function was called:

  • A new object in the case of a constructor.
  • undefined in strict mode function calls.
  • The base object if the function was called as an "object method".

This has proven to be less than ideal with an object-oriented style of programming.

Function Person() ( // The Person() constructor defines `this` as an instance of itself. this.age = 0; setInterval(function growUp() ( // In non-strict mode, the growUp() function defines ` this` // as the global object (because it"s where growUp() is executed.), // which is different from the `this` // defined by the Person() constructor. this.age++; ), 1000) ; ) var p = new Person();

In ECMAScript 3/5, the this issue was fixable by assigning the value in this to a variable that could be closed over.

Function Person() ( var that = this; that.age = 0; setInterval(function growUp() ( // The callback refers to the `that` variable of which // the value is the expected object. that.age++; ) , 1000); ) "use strict"; var obj = (a: 10); Object.defineProperty(obj, "b", ( get: () => ( console.log(this.a, typeof this.a, this); // undefined "undefined" Window (...) (or the global object) return this.a + 10; // represents global object "Window", therefore "this.a" returns "undefined" ) ));

Use of the new operator

Arrow functions cannot be used as constructors and will throw an error when used with new .

Var Foo = () => (); var foo = new Foo(); // TypeError: Foo is not a constructor

Use of prototype property

Arrow functions do not have a prototype property.

Var Foo = () => (); console.log(Foo.prototype); // undefined

Use of the yield keyword

The yield keyword may not be used in an arrow function"s body (except when permitted within functions further nested within it). As a consequence, arrow functions cannot be used as generators.

Function body

Arrow functions can have either a "concise body" or the usual "block body".

In a concise body, only an expression is specified, which becomes the implicit return value. In a block body, you must use an explicit return statement.

Var func = x => x * x; // concise body syntax, implied "return" var func = (x, y) => ( return x + y; ); // with block body, explicit "return" needed

Returning object literals

Keep in mind that returning object literals using the concise body syntax params => (object:literal) will not work as expected.

Var func = () => ( foo: 1 ); // Calling func() returns undefined! var func = () => ( foo: function() () ); // SyntaxError: function statement requires a name

This is because the code inside braces (()) is parsed as a sequence of statements (i.e. foo is treated like a label, not a key in an object literal).

You must wrap the object literal in parentheses:

Var func = () => (( foo: 1 ));

Line breaks

An arrow function cannot contain a line break between its parameters and its arrow.

Var func = (a, b, c) => 1; // SyntaxError: expected expression, got "=>"

However, this can be amended by putting the line break after the arrow or using parentheses/braces as seen below to ensure that the code stays pretty and fluffy. You can also put line breaks between arguments.

Var func = (a, b, c) => 1; var func = (a, b, c) => (1); var func = (a, b, c) => ( return 1 ); var func = (a, b, c) => 1; // no SyntaxError thrown

Parsing order

Although the arrow in an arrow function is not an operator, arrow functions have special parsing rules that interact differently with operator precedence compared to regular functions.

Let callback; callback = callback || function(); // ok callback = callback || () => (); // SyntaxError: invalid arrow-function arguments callback = callback || (() => ()); // ok

More examples // An empty arrow function returns undefined let empty = () => (); (() => "foobar")(); // Returns "foobar" // (this is an Immediately Invoked Function Expression) var simple = a => a > 15 ? 15: a; simple(16); // 15 simple(10); // 10 let max = (a, b) => a > b ? a: b; // Easy array filtering, mapping, ... var arr = ; var sum = arr.reduce((a, b) => a + b); // 66 var even = arr.filter(v => v % 2 == 0); // var double = arr.map(v => v * 2); // // More concise promise chains promise.then(a => ( // ... )).then(b => ( // ... )); // Parameterless arrow functions that are visually easier to parse setTimeout(() => ( console.log("I happen sooner"); setTimeout(() => ( // deeper code console.log("I happen later") ; ), eleven); Specifications Specification Status Comment
ECMAScript 2015 (6th Edition, ECMA-262)
Standard Initial definition.
ECMAScript Latest Draft (ECMA-262)
The definition of "Arrow Function Definitions" in that specification.
Draft
Browser compatibility

The compatibility table on this page is generated from structured data. If you"d like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.

Update compatibility data on GitHub

Desktop Mobile Server Chrome Edge Firefox Internet Explorer Opera Safari Android webview Chrome for Android Firefox for Android Opera for Android Safari on iOS Samsung Internet Node.jsArrow functions Trailing comma in parameters
Chrome Full support 45Edge Full support YesFirefox Full support 22

Notes

Full support 22

Notes

Notes Prior to Firefox 39, a line terminator (\n) was incorrectly allowed after arrow function arguments. This has been fixed to conform to the ES2015 specification and code like () \n =>
IE No support NoOpera Full support 32Safari Full support 10WebView Android Full support 45Chrome Android Full support 45Firefox Android Full support 22

Notes

Full support 22

Notes

Notes The initial implementation of arrow functions in Firefox made them automatically strict. This has been changed as of Firefox 24. The use of "use strict"; is now required. Notes Prior to Firefox 39, a line terminator (\n) was incorrectly allowed after arrow function arguments. This has been fixed to conform to the ES2015 specification and code like () \n => () will now throw a SyntaxError in this and later versions.
Opera Android Full support 32Safari iOS Full support 10Samsung Internet Android Full support 5.0nodejs Full support Yes
Chrome Full support 58Edge?Firefox Full support 52IE No support NoOpera Full support 45Safari?WebView Android Full support 58Chrome Android Full support 58Firefox Android Full support 52Opera Android Full support 43Safari iOS?Samsung Internet Android Full support 7.0nodejs Full support Yes
Legend Full support Full support No support No support Compatibility unknown Compatibility unknown See implementation notes. See implementation notes.
  • Tutorial

One of the most interesting parts of the new ECMAScript 6 standard is the arrow functions. Arrow functions, as the name suggests, are defined by a new syntax that uses an arrow => . However, in addition to their excellent syntax, arrow functions differ from traditional functions in other ways:

  • Lexical binding. Values special variables this , super , and arguments are determined not by how arrow functions were called, but by how they were created.
  • Immutable this , super and arguments . The values ​​of these variables inside arrow functions remain unchanged throughout life cycle functions.
  • Arrow functions cannot be used as a constructor and throw an error when used with the new operator.
  • Unavailability of the “native” value of the arguments variable.
There were several reasons for introducing these differences. The first one is that binding is used quite often in JavaScript. It is very easy to lose the correct this value when using traditional functions, which can lead to unexpected consequences. Another reason is that JS engines will be able to easily optimize the execution of arrow functions due to these restrictions (as opposed to traditional functions that can be used as a constructor and are free to modify special variables).


Note: This article is a compilation from a free translation of the article Understanding ECMAScript 6 arrow functions and a reading of the latest draft of the specification (January 20, 2014 Draft Rev 22).

Syntax In general, the syntax of arrow 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 arrow functions can vary depending on how you declare the function. The declaration always begins with a list of arguments, followed by an arrow and the body of the function. Both the argument list and the function body can take different forms, depending on what you write.

One parameter Declaring an arrow function that takes one argument and simply returns it is very simple:

Var reflect = value => value; // equivalent to var reflect = function(value) ( ​​return value; )
When an arrow function has only one argument, it can be declared without parentheses. The function body following the arrow may also have no curly braces and may not contain the return keyword.

Multiple parameters But if you want to declare more than one parameter, you must enclose the parameter list in parentheses:

Var sum = (num1, num2) => num1 + num2; // equivalent to var sum = function(num1, num2) ( return num1 + num2; );
The sum function simply adds 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; // equivalent to var sum = function() ( return 1 + 2; );

Traditional function body syntax You can use traditional function syntax for the body of an arrow function when it contains more than one expression. That is, wrap the function in curly braces and add the return keyword:

Var sum = (num1, num2) => ( return num1 + num2; ) // equivalent to var sum = function(num1, num2) ( return num1 + num2; );
The body of the function will be processed in exactly the same way as for classic functions, except that the values special variables this , super and arguments will be evaluated differently.

Object literal Separately, it should be mentioned that the body of a function that does not contain curly braces and simply returns an object literal should be enclosed in parentheses:

Var getTempItem = id => (( id: id, name: "Temp" )); // equivalent to var getTempItem = function(id) ( return ( id: id, name: "Temp" ) );
Placing an object literal in parentheses tells the parser that the curly braces are not the start of traditional syntax for a function body, but the start of a literal.

Variable number of parameters Since the “native” arguments object is not available inside an arrow function (the value of arguments is lexically related to the value of arguments of the traditional function within which the arrow function was declared), then for arrow functions with a variable number of parameters you need to use the rest pattern from destructuring patterns. Example:

Var getTempItems = (...rest) => rest; // equivalent to var getTempItems = function() ( return .slice.apply(arguments) );

Destructuring template as parameter For the purposes of this article, we do not consider destructuring patterns - you can read about them in the article Overview of ECMAScript 6, the next version of JavaScript, although this information is partially outdated.

As you can see from the previous example, even though the arrow function only has one argument, you still need to use parentheses when using destructuring patterns as the function's only parameter. Examples with others templates:

Var a = ((a)) => a; var b = ([b]) => b;

Using Arrow Functions Setting Context One common scenario in JavaScript is setting the correct this value inside a function (binding). Because the value of this can be changed, depending on the context in which the function is executed, it is possible to mistakenly act on one object when you meant something completely different. Look at the following example:

Var pageHandler = ( id: "123456" , init: function() ( document.addEventListener("click", function(event) ( this.doSomething(event.type); // error )); ) , doSomething: function( type) ( console.log("Handling " + type + " for " + this.id) ) );
In the above code, the pageHandler object should handle clicks on the page. The init() method attaches a handler to the desired event, which internally calls this.doSomething() . However, the code will not work correctly. The reference to this.doSomething() is not valid because this points to the document object inside the event handler instead of the intended pageHandler . If you try to run this code, you will get an error because the document object does not have a doSomething method.

You can bind the this value to the pageHandler object using handleEvent or by calling the standard bind() method on the function:

Var pageHandler = ( id: "123456" , init: function() ( document.addEventListener("click", (function(event) ( this.doSomething(event.type); // error )).bind(this)) ; ) , doSomething: function(type) ( console.log("Handling " + type + " for " + this.id) ) );
Now the code works as intended, but it looks more cumbersome. In addition, by calling bind(this) each time you create a new function whose this value is tied to the value of pageHandler , but the code works as you intended.

Arrow functions solve the problem in a more elegant way because they use lexical binding for the value of this (as well as super and arguments ) and its value is determined by the value of this at the location 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 an arrow function that calls this.doSomething() . The value of this will be the same as in the init() function, and the code in in this example will work correctly, similar to the one that used bind() . Regardless of whether the call to this.doSomething() returns a value or not, the expression inside the body of an arrow function does not need to be enclosed in curly braces.

In addition, the example above is also more efficient than calling bind() because it is the same as the following code for the browser:

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, creation does not occur new feature, as is the case with the bind() call.

“Throwing” the context between several calls Obviously, you can nest one arrow function within another, thereby “throwing” the this value through them:

Var obj = ( arr1: , arr2: ["a", "b", "c"] , concatenate: function(a, b)( return a + "|" + b ) , intersection: function() ( return this .arr1.reduce((sum, v1) => // arrow function 1 this.arr2.reduce((sum, v2) => ( // arrow function 2 sum.push(this.concatenate(v1, v2)) return sum; ) , sum) , ) ) ); var arrSum = obj.intersection();//["1|a", "1|b", "1|c", "2|a", "2|b", "2|c", "3 |a", "3|b", "3|c"]

Use as an argument The short syntax of arrow functions makes them ideal candidates for passing as arguments to other function calls. For example, if you want to sort an array, you would usually write something like this:

Var result = values.sort(function(a, b) ( return a - b ));
Quite verbose for a simple operation. Compare with the short notation for an arrow function:

Var result = values.sort((a, b) => a - b);
The use of methods such as array() , map() , reduce() and so on can be simplified using short arrow function syntax.

Other Features of Arrow Functions Although arrow functions are different from traditional functions, they have some common features:
  • The typeof operator will return "function" for an arrow function
  • An arrow function is also an instance of the Function "class", so instanceof will work the same as with a 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, however it will not change the value of super ( the toMethod() method was introduced in es6 and is not covered in this article).
A significant difference from traditional functions is that an attempt to call an arrow function using the new operator will cause a runtime error. Summary Arrow functions are one of the most interesting innovations in ECMAScript 6, which, having a concise definition syntax, will simplify the passing of functions as a parameter value to another function.

Concise syntax will allow you to write complex things even more complexly in a simpler way. For example, this is what the identifier generator will look like (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());//100 101 10 10
And lexical binding will close one of the biggest sources of pain and frustration for developers, and will also improve performance due to optimization at the js engine level.


If you want to try arrow functions, you can run the above examples in the Firefox console, which is on this moment(02.2014 FF28) almost fully supports arrow functions (FF28 incorrectly calculates the value of arguments ).

You can also try arrow functions and other es6 features in the online translator Traceur.

Tags: Add tags