Arrow functions

  • Revision slug: Web/JavaScript/Reference/arrow_functions
  • Revision title: Arrow functions
  • Revision id: 425443
  • Created:
  • Creator: WebReflection
  • Is current revision? No
  • Comment

Revision Content

{{Harmony()}}

Summary

An arrow function expression has a shorter syntax compared to function expressions and lexically binds the this value. Arrow functions are always anonymous.

Expression
Implemented in: Firefox 22 (SpiderMonkey 22)
ECMA Version: ECMAScript 6th Edition (Draft)

Syntax

([param] [, param]) => {
   statements
}

param => expression

Parameters

param
The name of an argument. Zero arguments need to be indicated with ().  For only one argument the parentheses are not required. (like foo => 1)
statements or expression
Multiple statements need to be enclosed in brackets. A single expression however requires no brackets. The expression is also the implicit return value of that function.

Description

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 = [
  "We're up all night 'til the sun",
  "We're up all night to get some",
  "We're up all night for good fun",
  "We're up all night to get lucky"
];

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

var a3 = a.map( s => s.length );

Lexical this

Until arrow functions, all 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(){
    this.age = 0;

    setInterval(function growUp(){
        // not the |this| you expect 
        this.age++; // global object in non-strict mode, which will have a hard to discover misbehavior
    }, 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 which value is the expected object
        self.age++;
    }, 1000);
}

Alternatively, a bound function could be created so that the proper this value is 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 when it comes 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.

Upcoming change

Currently, in Firefox implementation, the body of all arrow functions is strict (without the need for the "use strict"; directive). This is meant to change in the near future to match the latest TC39 agreement.

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

var complex = (a, b) => {
    if (a > b) {
        return a;
    } else {
        return b;
    }
}

Specification

 

Browser compatibility

{{ CompatibilityTable() }}

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
Basic support {{ CompatNo() }} {{ CompatGeckoDesktop("22") }} {{ CompatNo() }} {{ CompatNo() }} {{ CompatNo() }}
Feature Android Firefox Mobile (Gecko) IE Phone Opera Mobile Safari Mobile
Basic support {{ CompatNo() }} {{ CompatGeckoMobile("22") }} {{ CompatNo() }} {{ CompatNo() }} {{ CompatNo() }}

 

Revision Source

<p>{{Harmony()}}</p>
<h2 id="Summary" name="Summary">Summary</h2>
<p>An arrow function expression has a shorter syntax compared to function expressions and lexically binds the this value. Arrow functions are always anonymous.</p>
<table class="standard-table">
  <tbody>
    <tr>
      <td class="header" colspan="2">Expression</td>
    </tr>
    <tr>
      <td>Implemented in:</td>
      <td>Firefox 22 (SpiderMonkey 22)</td>
    </tr>
    <tr>
      <td>ECMA Version:</td>
      <td>ECMAScript 6th Edition (Draft)</td>
    </tr>
  </tbody>
</table>
<h2 id="Syntax" name="Syntax">Syntax</h2>
<pre class="syntaxbox">
([param] [, param]) =&gt; {
   statements
}

param =&gt; expression</pre>
<h3 id="Parameters" name="Parameters">Parameters</h3>
<dl>
  <dt>
    <code>param</code></dt>
  <dd>
    The name of an argument. Zero arguments need to be indicated with <code>()</code>.&nbsp; For only one argument the <span class="mw-headline" id="Parentheses_.28_.29">parentheses</span> are not required. (like <code>foo =&gt; 1</code>)</dd>
  <dt>
    <code>statements or expression</code></dt>
  <dd>
    Multiple statements need to be enclosed in brackets. A single expression however requires no brackets. The expression is also the implicit return value of that function.</dd>
</dl>
<h2 id="Description">Description</h2>
<p>Two factors influenced the introduction of arrow functions: shorter functions and lexical this.</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 = [
  "We're up all night 'til the sun",
  "We're up all night to get some",
  "We're up all night for good fun",
  "We're up all night to get lucky"
];

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, all new function defined its own <a href="/en-US/docs/Web/JavaScript/Reference/Operators/this" title="/en-US/docs/Web/JavaScript/Reference/Operators/this">this</a> 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.</p>
<pre class="brush: js">
<span class="kd">function</span> <span class="nx">Person</span><span class="p">(){</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

    <span class="nx">setInterval</span><span class="p">(</span><span class="kd">function</span> <span class="nx">growUp</span><span class="p">(){</span>
        // not the |this| you expect 
        <span class="k">this</span><span class="p">.</span><span class="nx">age</span><span class="o">++</span><span class="p">;</span> // global object in non-strict mode, which will have a hard to discover misbehavior
    <span class="p">},</span> <span class="mi">1000</span><span class="p">);</span>
<span class="p">}</span>

<span class="kd">var</span> <span class="nx">p</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Person</span><span class="p">();</span></pre>
<p>In ECMAScript 3/5, this issue was fixed by assigning the value in <code>this</code> to a variable that could be closed over.</p>
<pre class="brush: js">
<span class="kd">function</span> <span class="nx">Person</span><span class="p">(){</span>
    <span class="kd">var</span> <span class="nx">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span> <span class="c1">// some choose 'that' instead of 'self'. Choose one and be consistent</span>
    <span class="nx">self</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

    <span class="nx">setInterval</span><span class="p">(</span><span class="kd">function</span> <span class="nx">growUp</span><span class="p">(){</span>
         <span class="c1">// the callback refers to the self variable which value is the expected object</span>
        <span class="nx">self</span><span class="p">.</span><span class="nx">age</span><span class="o">++</span><span class="p">;</span>
    <span class="p">},</span> <span class="mi">1000</span><span class="p">);</span>
<span class="p">}</span></pre>
<p><span class="p">Alternatively, a <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind" title="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">bound function</a> </span>could be created so that the proper <code>this</code> value is passed to the <code>growUp</code> function.</p>
<p>Arrow functions capture the <code>this</code> value of the enclosing context, so the following code works as expected.</p>
<pre class="brush: js">
<span class="kd">function</span> <span class="nx">Person</span><span class="p">(){</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

    <span class="nx">setInterval</span><span class="p">(</span><span class="p">() =&gt; {</span>
        <span class="k">this</span><span class="p">.</span><span class="nx">age</span><span class="o">++</span><span class="p">;</span> // |this| properly refers to the person object
    <span class="p">},</span> <span class="mi">1000</span><span class="p">);</span>
<span class="p">}</span>

<span class="kd">var</span> <span class="nx">p</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Person</span><span class="p">();</span></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/Functions_and_function_scope/Strict_mode" title="/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode">strict mode</a> rules when it comes 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>
<h3 id="Upcoming_change">Upcoming change</h3>
<p>Currently, in Firefox implementation, the body of all arrow functions is <a href="/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode" title="/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode">strict</a> (without the need for the <code>"use strict";</code> directive). This is <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=852762" title="https://bugzilla.mozilla.org/show_bug.cgi?id=852762">meant to change in the near future</a> to match the latest TC39 agreement.</p>
<h2 id="Examples">Examples</h2>
<pre class="brush: js">
<span class="co1">// An empty arrow function returns undefined</span>
let empty = () =&gt; {};

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

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

var complex = (a, b) =&gt; {
&nbsp;&nbsp;&nbsp; if (a &gt; b) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return a;
&nbsp;&nbsp;&nbsp; } else {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return b;
&nbsp;&nbsp;&nbsp; }
}</pre>
<h2 id="Specification">Specification</h2>
<ul>
  <li><a href="http://wiki.ecmascript.org/doku.php?id=harmony:arrow_function_syntax" title="http://wiki.ecmascript.org/doku.php?id=harmony:arrow_function_syntax">Harmony proposal</a></li>
  <li><a href="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-13.2" title="http://people.mozilla.org/~jorendorff/es6-draft.html#sec-13.2">Draft spec</a></li>
</ul>
<p>&nbsp;</p>
<h2 id="Browser_Compatibility" name="Browser_Compatibility">Browser compatibility</h2>
<p>{{ CompatibilityTable() }}</p>
<div id="compat-desktop">
  <table class="compat-table">
    <tbody>
      <tr>
        <th>Feature</th>
        <th>Chrome</th>
        <th>Firefox (Gecko)</th>
        <th>Internet Explorer</th>
        <th>Opera</th>
        <th>Safari (WebKit)</th>
      </tr>
      <tr>
        <td>Basic support</td>
        <td>{{ CompatNo() }}</td>
        <td>{{ CompatGeckoDesktop("22") }}</td>
        <td>{{ CompatNo() }}</td>
        <td>{{ CompatNo() }}</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>Firefox Mobile (Gecko)</th>
        <th>IE Phone</th>
        <th>Opera Mobile</th>
        <th>Safari Mobile</th>
      </tr>
      <tr>
        <td>Basic support</td>
        <td>{{ CompatNo() }}</td>
        <td>{{ CompatGeckoMobile("22") }}</td>
        <td>{{ CompatNo() }}</td>
        <td>{{ CompatNo() }}</td>
        <td>{{ CompatNo() }}</td>
      </tr>
    </tbody>
  </table>
</div>
<p>&nbsp;</p>
Revert to this revision