Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Revision 1089993 of Arrow functions

  • Revision slug: Web/JavaScript/Reference/Functions/Arrow_functions
  • Revision title: Arrow functions
  • Revision id: 1089993
  • Created:
  • Creator: fscholz
  • Is current revision? No
  • Comment review

Revision Content

{{jsSidebar("Functions")}}

An arrow function expression has a shorter syntax compared to function expressions and lexically binds the this value (does not bind its own thisargumentssuper, or new.target). Arrow functions are always anonymous. These function expression are best suited for non-method functions.

Syntax

Basic Syntax

(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
         // equivalent to:  => { return expression; }

// Parentheses are optional when there's only one parameter:
(singleParam) => { statements }
singleParam => { statements }

// A function with no parameters requires parentheses:
() => { statements }

Advanced Syntax

// Parenthesize the body 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 = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f();  // 6

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",
  "Beryl­lium"
];

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 non-strict 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.

An arrow function does not create it's own this context, rather it captures 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

Lexical arguments

Arrow functions do not expose an arguments object to their code: arguments.length, arguments[0], arguments[1], and so forth do not refer to the arguments provided to the arrow function when called.  Instead, arguments is simply a reference to the name in the enclosing scope.

var arguments = 42;
var arr = () => arguments;

arr(); // 42

function foo() {
  var f = (i) => arguments[0]+i; // foo's implicit arguments binding
  return f(2);
}

foo(1); // 3

Arrow functions don't have their own arguments object, but in most cases rest parameters are a good alternative:

function foo() { 
  var f = (...args) => args[0]; 
  return f(2); 
}

foo(1); // 2

Arrow functions used as methods

As stated, arrow function expressions are best suited for non-method functions. Let's see what happens when we try to use them as methods.

'use strict';
var obj = {
  i: 10,
  b: () => console.log(this.i, this),
  c: function() {
    console.log( this.i, this)
  }
}
obj.b(); // prints undefined, Window
obj.c(); // prints 10, Object {...}

The binding of the lexical this occurs differently in case of arrow functions. Another example involving {{jsxref("Object.defineProperty()")}}:

'use strict';
var obj = {
  a: 10
};

Object.defineProperty(obj, "b", {
  get: () => {
    console.log(this.a, typeof this.a, this);
    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.

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".

The block body form doesn't automatically return a value. You need to use an explicit return statement,

But with concise body where there is only an expression in function body, there is an implict return attached. 

var func = x => x * x;                  // concise 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 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")() // IIFE, 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]

// More concise promise chains
promise.then(a => {
  // ...
}).then(b => {
   // ...
});

Specifications

Specification Status Comment
{{SpecName('ES6', '#sec-arrow-function-definitions', 'Arrow Function Definitions')}} {{Spec2('ES6')}} Initial definition.
{{SpecName('ESDraft', '#sec-arrow-function-definitions', 'Arrow Function Definitions')}} {{Spec2('ESDraft')}}  

Browser compatibility

{{CompatibilityTable}}
Feature Chrome Firefox (Gecko) Edge IE Opera Safari
Basic support {{CompatChrome(45.0)}} {{CompatGeckoDesktop("22.0")}} {{CompatVersionUnknown}}

{{CompatNo}}

{{CompatOpera(32)}} {{CompatNo}}
Feature Android Android Webview Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile Chrome for Android
Basic support {{CompatNo}} {{CompatChrome(45.0)}} {{CompatGeckoMobile("22.0")}} {{CompatNo}} {{CompatNo}} {{CompatNo}} {{CompatChrome(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 {{jsxref("Operators/Expression_Closures", "expression closures", "", 1)}} added in Firefox 3 (details: JavaScript 1.8), for {{jsxref("Operators/Expression_Closures", "expression closures", "", 1)}} 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 a {{jsxref("SyntaxError")}} in this and later versions.

See also

Revision Source

<div>{{jsSidebar("Functions")}}</div>

<p>An <strong>arrow function expression</strong> has a shorter syntax compared to <a href="/en-US/docs/Web/JavaScript/Reference/Operators/function">function expressions</a> and lexically binds&nbsp;the <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/this">this</a></code> value (does not bind&nbsp;its own&nbsp;<code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/this">this</a></code>,&nbsp;<a href="/en-US/docs/Web/JavaScript/Reference/Functions/arguments">arguments</a>,&nbsp;<a href="/en-US/docs/Web/JavaScript/Reference/Operators/super">super</a>, or&nbsp;<a href="/en-US/docs/Web/JavaScript/Reference/Operators/new.target">new.target</a>). Arrow functions are always <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name">anonymous</a>. These function expression are best suited for non-method functions.</p>

<h2 id="Syntax">Syntax</h2>

<h3 id="Basic_Syntax">Basic Syntax</h3>

<pre class="syntaxbox">
<strong>(</strong><em>param1</em>, <em>param2</em>, …, <em>paramN</em><strong>) =&gt; {</strong> <em>statements</em> <strong>}</strong>
<strong>(</strong><em>param1</em>, <em>param2</em>, …, <em>paramN</em><strong>) =&gt;</strong> <em>expression</em>
         // equivalent to:&nbsp; =&gt; { return expression; }

// Parentheses are optional when there's only one parameter:
<em>(singleParam)</em> <strong>=&gt; {</strong> <em>statements</em> <strong>}</strong>
<em>singleParam</em> <strong>=&gt;</strong> { <em>statements }</em>

// A function with no parameters requires parentheses:
<strong>() =&gt; {</strong> <em>statements</em> <strong>}</strong></pre>

<h3 id="Advanced_Syntax">Advanced Syntax</h3>

<pre class="syntaxbox">
// Parenthesize the body to return an object literal expression:
<em>params</em> =&gt; ({<em>foo: bar</em>})

// <a href="/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters">Rest parameters</a> and <a href="/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters">default parameters</a> are supported
(<em>param1</em>, <em>param2</em>, <strong>...rest</strong>) =&gt; { <em>statements</em> }
(<em>param1</em> <strong>= defaultValue1</strong>, <em>param2</em>, …, paramN <strong>= defaultValueN</strong>) =&gt; { <em>statements</em> }

// <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">Destructuring</a> within the parameter list is also supported
var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) =&gt; a + b + c;
f();  // 6
</pre>

<p>Detailed syntax examples can be seen <a href="https://wiki.ecmascript.org/doku.php?id=harmony:arrow_function_syntax">here</a>.</p>

<h2 id="Description">Description</h2>

<p>See also <a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">"ES6 In Depth: Arrow functions" on hacks.mozilla.org</a>.</p>

<p>Two factors influenced the introduction of arrow functions: shorter functions and lexical <code>this</code>.</p>

<h3 id="Shorter_functions">Shorter functions</h3>

<p>In some functional patterns, shorter functions are welcome. Compare:</p>

<pre class="brush: js">
var a = [
  "Hydrogen",
  "Helium",
  "Lithium",
  "Beryl­lium"
];

var a2 = a.map(function(s){ return s.length });

var a3 = a.map( s =&gt; s.length );</pre>

<h3 id="Lexical_this">Lexical <code>this</code></h3>

<p>Until arrow functions, every new function defined its own <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/this">this</a></code> value (a new object in case of a constructor, undefined in <a href="/en-US/docs/Web/JavaScript/Reference/Strict_mode">strict mode</a> function calls, the context object if the function is called as an "object method", etc.). <code>This</code> proved to be annoying with an object-oriented style of programming.</p>

<pre class="brush: js">
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, which is different from the `this`
    // defined by the Person() constructor.
    this.age++;
  }, 1000);
}

var p = new Person();</pre>

<p>In ECMAScript 3/5, <code>this</code> issue was fixed by assigning the value in <code>this</code> to a variable that could be closed over.</p>

<pre class="brush: js">
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);
}</pre>

<p>Alternatively, a <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">bound function</a> could be created so that the proper <code>this</code> value would be passed to the <code>growUp()</code> function.</p>

<p>An arrow function&nbsp;does not create it's own <code>this</code> context, rather it&nbsp;captures the&nbsp;<code>this</code> value of the enclosing context, so the following code works as expected.</p>

<pre class="brush: js">
function Person(){
  this.age = 0;

  setInterval(() =&gt; {
    this.age++; // |this| properly refers to the person object
  }, 1000);
}

var p = new Person();</pre>

<h4 id="Relation_with_strict_mode">Relation with strict mode</h4>

<p>Given that <code>this</code> is lexical, <a href="/en-US/docs/Web/JavaScript/Reference/Strict_mode">strict mode</a> rules with regard to <code>this</code> are just ignored.</p>

<pre class="brush: js">
var f = () =&gt; {'use strict'; return this};
f() === window; // or the global object</pre>

<p>The rest of strict mode rules apply normally.</p>

<h4 id="Invoked_through_call_or_apply">Invoked through call or apply</h4>

<p>Since <code>this</code><em> </em>is already bound lexically, invoking an arrow function through the <code>call()</code><em> </em>or <code>apply()</code> methods can only pass in arguments, but has no effect on <code>this</code>:</p>

<pre class="brush: js">
var adder = {
  base : 1,
&nbsp;&nbsp; &nbsp;
  add : function(a) {
    var f = v =&gt; v + this.base;
    return f(a);
  },

  addThruCall: function(a) {
    var f = v =&gt; v + this.base;
    var b = {
      base : 2
    };
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;
    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</pre>

<h3 id="Lexical_arguments">Lexical <code>arguments</code></h3>

<p>Arrow functions do not expose an <a href="/en-US/docs/Web/JavaScript/Reference/Functions/arguments"><code>arguments</code> object</a> to their code: <code>arguments.length</code>, <code>arguments[0]</code>, <code>arguments[1]</code>, and so forth do not refer to the arguments provided to the arrow function when called.&nbsp; Instead, <code>arguments</code> is simply a reference to the name in the enclosing scope.</p>

<pre class="brush: js">
var arguments = 42;
var arr = () =&gt; arguments;

arr(); // 42

function foo() {
  var f = (i) =&gt; arguments[0]+i; // <em>foo</em>'s implicit arguments binding
  return f(2);
}

foo(1); // 3</pre>

<p>Arrow functions don't have their own <code>arguments</code> object, but in most cases <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters">rest parameters</a> are a good alternative:</p>

<pre class="brush: js">
function foo() { 
  var f = (...args) =&gt; args[0]; 
  return f(2); 
}

foo(1); // 2</pre>

<h3 id="Arrow_Functions_when_used_as_Methods">Arrow functions used as methods</h3>

<p>As stated, arrow function expressions are best suited for non-method functions. Let's see what happens when we try to use them as methods.</p>

<pre class="brush: js">
'use strict';
var obj = {
&nbsp; i: 10,
&nbsp; b: () =&gt; console.log(this.i, this),
&nbsp; c: function() {
&nbsp; &nbsp; console.log( this.i, this)
&nbsp; }
}
obj.b(); // prints undefined, Window
obj.c(); // prints 10, Object {...}</pre>

<p>The binding of the lexical <code>this</code> occurs differently in case of arrow functions. Another example involving {{jsxref("Object.defineProperty()")}}:</p>

<pre class="brush: js">
'use strict';
var obj = {
  a: 10
};

Object.defineProperty(obj, "b", {
  get: () =&gt; {
    console.log(this.a, typeof this.a, this);
    return this.a+10; // represents global object 'Window', therefore 'this.a' returns 'undefined'
  }
});
</pre>

<h3 id="Use_of_the_new_operator">Use of the <code>new</code> operator</h3>

<p>Arrow functions cannot be used as constructors and will throw an error when used with <code>new</code>.</p>

<h3 id="Use_of_the_yield_keyword">Use of the <code>yield</code> keyword</h3>

<p>The <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/yield">yield</a></code>&nbsp;keyword&nbsp;may not be used in an arrow function's body (except when permitted within functions further nested within it).&nbsp; As a consequence, arrow functions cannot be used as generators.</p>

<h2 id="Function_body">Function body</h2>

<p>Arrow functions can have either a "concise body" or the usual "block body".</p>

<p>The block body form doesn't automatically return a value. You need to use an explicit&nbsp;<code>return</code> statement,</p>

<p>But with concise body where there is only an expression in function body, there is an implict return attached.&nbsp;</p>

<pre class="brush: js">
var func = x =&gt; x * x;                  // concise syntax, implied "return"
var func = (x, y) =&gt; { return x + y; }; // with block body, explicit "return" needed
</pre>

<h2 id="Returning_object_literals">Returning object literals</h2>

<p>Keep in mind that returning object literals using the concise&nbsp;syntax <code>params =&gt; {object:literal}</code> will not work as expected:</p>

<pre class="brush: js">
var func = () =&gt; {&nbsp; foo: 1&nbsp; };               // Calling func() returns undefined!
var func = () =&gt; {&nbsp; foo: function() {}&nbsp; };   // SyntaxError: function statement requires a name</pre>

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

<p>Remember to wrap the object literal in parentheses:</p>

<pre class="brush: js">
var func = () =&gt; ({ foo: 1 });</pre>

<h2 id="Examples">Examples</h2>

<pre class="brush: js">
// An empty arrow function returns undefined
let empty = () =&gt; {};

(() =&gt; "foobar")() // IIFE, returns "foobar" 

var simple = a =&gt; a &gt; 15 ? 15 : a; 
simple(16); // 15
simple(10); // 10

let max = (a, b) =&gt; a &gt; b ? a : b;

// Easy array filtering, mapping, ...

var arr = [5, 6, 13, 0, 1, 18, 23];
var sum = arr.reduce((a, b) =&gt; a + b);  // 66
var even = arr.filter(v =&gt; v % 2 == 0); // [6, 0, 18]
var double = arr.map(v =&gt; v * 2);       // [10, 12, 26, 0, 2, 36, 46]

// More concise promise chains
promise.then(a =&gt; {
&nbsp; // ...
}).then(b =&gt; {
&nbsp;  // ...
});</pre>

<h2 id="Specifications">Specifications</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Specification</th>
   <th scope="col">Status</th>
   <th scope="col">Comment</th>
  </tr>
  <tr>
   <td>{{SpecName('ES6', '#sec-arrow-function-definitions', 'Arrow Function Definitions')}}</td>
   <td>{{Spec2('ES6')}}</td>
   <td>Initial definition.</td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-arrow-function-definitions', 'Arrow Function Definitions')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td>&nbsp;</td>
  </tr>
 </tbody>
</table>

<h2 id="Browser_compatibility">Browser compatibility</h2>

<div>{{CompatibilityTable}}</div>

<div id="compat-desktop">
<table class="compat-table">
 <tbody>
  <tr>
   <th>Feature</th>
   <th>Chrome</th>
   <th>Firefox (Gecko)</th>
   <th>Edge</th>
   <th>IE</th>
   <th>Opera</th>
   <th>Safari</th>
  </tr>
  <tr>
   <td>Basic support</td>
   <td>{{CompatChrome(45.0)}}</td>
   <td>{{CompatGeckoDesktop("22.0")}}</td>
   <td>{{CompatVersionUnknown}}</td>
   <td>
    <p>{{CompatNo}}</p>
   </td>
   <td>{{CompatOpera(32)}}</td>
   <td>{{CompatNo}}</td>
  </tr>
 </tbody>
</table>
</div>

<div id="compat-mobile">
<table class="compat-table">
 <tbody>
  <tr>
   <th>Feature</th>
   <th>Android</th>
   <th>Android Webview</th>
   <th>Firefox Mobile (Gecko)</th>
   <th>IE Mobile</th>
   <th>Opera Mobile</th>
   <th>Safari Mobile</th>
   <th>Chrome for Android</th>
  </tr>
  <tr>
   <td>Basic support</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatChrome(45.0)}}</td>
   <td>{{CompatGeckoMobile("22.0")}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatChrome(45.0)}}</td>
  </tr>
 </tbody>
</table>
</div>

<h2 id="Firefox-specific_notes">Firefox-specific notes</h2>

<ul>
 <li>The initial implementation of arrow functions in Firefox made them automatically strict. This has been changed as of <a href="/en-US/docs/Mozilla/Firefox/Releases/24">Firefox 24</a>. The use of <code>"use strict";</code> is now required.</li>
 <li>Arrow functions are semantically different from the non-standard {{jsxref("Operators/Expression_Closures", "expression closures", "", 1)}} added in <a href="/en-US/Firefox/Releases/3">Firefox 3</a> (details: <a href="/en-US/docs/Web/JavaScript/New_in_JavaScript/1.8">JavaScript 1.8</a>), for {{jsxref("Operators/Expression_Closures", "expression closures", "", 1)}} do not bind <code>this</code> lexically.</li>
 <li>Prior to <a href="/en-US/Firefox/Releases/39">Firefox 39</a>, a line terminator (<code>\n</code>) was incorrectly allowed after arrow function arguments. This has been fixed to conform to the ES6 specification and code like <code>() \n =&gt; {}</code> will now throw a {{jsxref("SyntaxError")}} in this and later versions.</li>
</ul>

<h2 id="See_also">See also</h2>

<ul>
 <li><a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">"ES6 In Depth: Arrow functions" on hacks.mozilla.org</a></li>
</ul>
Revert to this revision