This is a new technology, part of the ECMAScript 2015 (ES6) standard.
This technology's specification has been finalized, but check the compatibility table for usage and implementation status in various browsers.
An arrow function expression (also known as fat arrow function) has a shorter syntax compared to function expressions and lexically binds the this value. Arrow functions are always anonymous.
Syntax
// Basic syntax: (param1, param2, paramN) => { statements } (param1, param2, paramN) => expression // equivalent to: => { return expression; } // Parentheses are optional when there's only one argument: singleParam => { statements } singleParam => expression // A function with no arguments requires parentheses: () => { statements } // Advanced: // Parenthesize the body to return an object literal expression: params => ({foo: bar}) // Rest parameters are supported (param1, param2, ...rest) => { statements }
Detailed syntax examples can be seen here.
Description
See also "ES6 In Depth: Arrow functions" on hacks.mozilla.org.
Two factors influenced the introduction of arrow functions: shorter functions and lexical this
.
Shorter functions
In some functional patterns, shorter functions are welcome. Compare:
var a = [ "Hydrogen", "Helium", "Lithium", "Beryllium" ]; var a2 = a.map(function(s){ return s.length }); var a3 = a.map( s => s.length );
Lexical this
Until arrow functions, every new function defined its own this
value (a new object in case of a constructor, undefined in strict mode function calls, the context object if the function is called as an "object method", etc.). This proved to be annoying 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 nonstrict mode, the growUp() function defines `this`
// as the global object, which is different from the `this`
// defined by the Person() constructor.
this.age++;
}, 1000);
}
var p = new Person();
In ECMAScript 3/5, this issue was fixed by assigning the value in this
to a variable that could be closed over.
function Person() { var self = this; // Some choose `that` instead of `self`. // Choose one and be consistent. self.age = 0; setInterval(function growUp() { // The callback refers to the `self` variable of which // the value is the expected object. self.age++; }, 1000); }
Alternatively, a bound function could be created so that the proper this
value would be passed to the growUp()
function.
Arrow functions capture the this
value of the enclosing context, so the following code works as expected.
function Person(){ this.age = 0; setInterval(() => { this.age++; // |this| properly refers to the person object }, 1000); } var p = new Person();
Relation with strict mode
Given that this
is lexical, strict mode rules with regard to this
are just ignored.
var f = () => {'use strict'; return this}; f() === window; // or the global object
The rest of strict mode rules apply normally.
Invoked through call or apply
Since this
is already bound lexically, invoking an arrow function through the call()
or apply()
methods can only pass in arguments, but has no effect on this
:
var adder = { base : 1, add : function(a) { var f = v => v + this.base; return f(a); }, addThruCall: function(a) { var f = v => v + this.base; var b = { base : 2 }; return f.call(b, a); } }; console.log(adder.add(1)); // This would log to 2 console.log(adder.addThruCall(1)); // This would log to 2 still
Use of arguments object or yield keyword
The arguments
object may not be used inside the body of an arrow function. Likewise, the yield
keyword may not be used inside an arrow function's body and an arrow function may not be used as a generator.
Returning object literals
Keep in mind that returning object literals using the consise 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).
Remember to wrap the object literal in parentheses:
var func = () => ({ foo: 1 });
Examples
// An empty arrow function returns undefined let empty = () => {}; (() => "foobar")() // returns "foobar" 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 = [5, 6, 13, 0, 1, 18, 23]; var sum = arr.reduce((a, b) => a + b); // 66 var even = arr.filter(v => v % 2 == 0); // [6, 0, 18] var double = arr.map(v => v * 2); // [10, 12, 26, 0, 2, 36, 46]
Specifications
Specification | Status | Comment |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'Arrow Function Definitions' in that specification. |
Standard | Initial definition. |
Browser compatibility
Feature | Chrome | Firefox (Gecko) | IE/Edge | Opera | Safari |
---|---|---|---|---|---|
Basic support | 45.0 | 22.0 (22.0) |
Edge 12 |
32 | Not supported |
Feature | Android | Android Webview | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile | Chrome for Android |
---|---|---|---|---|---|---|---|
Basic support | Not supported | 45.0 | 22.0 (22.0) | Not supported | Not supported | Not supported | 45.0 |
Firefox-specific 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. - Arrow functions are semantically different from the non-standard Expression Closures added in Firefox 3 (details: Javascript 1.8), for Expression Closures do not bind
this
lexically. - Prior to Firefox 39, a line terminator (
\n
) was incorrectly allowed after arrow function arguments. This has been fixed to conform to the ES6 specification and code like() \n => {}
will now throw aSyntaxError
in this and later versions.