Atoow Assignment

An arrow function expression has a shorter syntax than a function expression and does not have its own , arguments, super, or new.target. These function expressions are best suited for non-method functions, 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 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 = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c; f(); // 6

Description

See also "ES6 In Depth: Arrow functions" on hacks.mozilla.org.

Two factors influenced the introduction of arrow functions: shorter functions and non-binding of .

Shorter functions

var materials = [ 'Hydrogen', 'Helium', 'Lithium', 'Beryllium' ]; materials.map(function(material) { return material.length; }); // [8, 6, 7, 9] materials.map((material) => { return material.length; }); // [8, 6, 7, 9] materials.map(({length}) => length); // [8, 6, 7, 9]

No separate

Until arrow functions, every new function defined its own value (a new object in the case of a constructor, undefined in strict mode function calls, the base object if the function is called as an "object method", etc.). This proved 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 issue was fixable by assigning the value in 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); }

Alternatively, a bound function could be created so that a preassigned value would be passed to the bound target function (the function in the example above).

An arrow function does not newly define its own  when it's being executed in the global context; instead, the value of the enclosing execution context is used, equivalent to treating  as closure value.  Thus, in the following code, the within the function that is passed to has the same value as in the enclosing function:

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  comes from the surrounding lexical context, strict mode rules with regard to are ignored.

function Person() {   this.age = 0;   var closure = "123"   setInterval(function growUp() {     this.age++;     console.log(closure)   }, 1000); } var p = new Person(); function PersonX() {   'use strict'   this.age = 0;   var closure = "123"   setInterval(()=>{     this.age++;     console.log(closure)   }, 1000); } var px = new PersonX();

All other strict mode rules apply normally.

Invoked through call or apply

Since arrow functions do not have their own , the methods or can only pass in parameters. is ignored.

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

No binding of

Arrow functions do not have their own object. Thus, in this example, is simply a reference to the arguments of the enclosing scope:

var arguments = [1, 2, 3]; var arr = () => arguments[0]; arr(); // 1 function foo(n) { var f = () => arguments[0] + n; // foo's implicit arguments binding. arguments[0] is n return f(); } foo(1); // 2

In most cases, using rest parameters is a good alternative to using an object.

function foo(n) { var f = (...args) => args[0] + n; return f(10); } foo(1); // 11

Arrow functions used as methods

As stated previously, 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 {...} (or the global object) obj.c(); // prints 10, Object {...}

Arrow functions do not have their own . Another example involving :

'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 operator

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

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

Use of property

Arrow functions do not have a property.

var Foo = () => {}; console.log(Foo.prototype); // undefined

Use of the keyword

The 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 explicit return value. In a block body, you must use an explicit 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 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. is treated like a label, not a key in an object literal).

Remember to 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 = () => 1; // SyntaxError: expected expression, got '=>'

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 // see 'IIFE' in glossary) 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 => { // ... }); // Parameterless arrow functions that are visually easier to parse setTimeout( () => { console.log('I happen sooner'); setTimeout( () => { // deeper code console.log('I happen later'); }, 1); }, 1);

Specifications

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.

FeatureChromeEdgeFirefoxInternet ExplorerOperaSafari
Basic support45 Yes2212 No3210
Trailing comma in parameters58 ?52 No45 ?
FeatureAndroid webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
Basic support4545 Yes22123210 ?
Trailing comma in parameters5858 ?5245 ? ?

1. The initial implementation of arrow functions in Firefox made them automatically strict. This has been changed as of Firefox 24. The use of is now required.

2. Prior to Firefox 39, a line terminator () was incorrectly allowed after arrow function arguments. This has been fixed to conform to the ES2015 specification and code like will now throw a in this and later versions.

DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidEdge MobileFirefox for AndroidOpera for AndroidiOS SafariSamsung InternetNode.js
Basic supportFull support 45Full support YesFull 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 is now required.
Notes Prior to Firefox 39, a line terminator () was incorrectly allowed after arrow function arguments. This has been fixed to conform to the ES2015 specification and code like will now throw a in this and later versions.
No support NoFull support 32Full support 10Full support 45Full support 45Full support YesFull 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 is now required.
Notes Prior to Firefox 39, a line terminator () was incorrectly allowed after arrow function arguments. This has been fixed to conform to the ES2015 specification and code like will now throw a in this and later versions.
Full support 32Full support 10 ? Full support Yes
Trailing comma in parametersFull support 58 ? Full support 52No support NoFull support 45 ? Full support 58Full support 58 ? Full support 52Full support 45 ? ? ?

Legend

Full support
Full support
No support
No support
Compatibility unknown
Compatibility unknown
See implementation notes.
See implementation notes.

See also

Document Tags and Contributors

 Contributors to this page:martian2049, akinjide, the94air, iigmir, wbamberg, Kng00, mlb, SphinxKnight, vidyasagarg1222, mariusschulz, CodeFry, all-user, hkdnet, torazaburo, Audaciter, fscholz, jodamn, Keavon, jreut, yangshun, Robg1, fernandosavio, NailSalikhov, alex-wilmer, zekrom-vale, jameshkramer, xgqfrms-GitHub, SibrenTalens, Sebastianz, PhillipSenn, leobalter, nikhilgoyal104ah4, harkirat1892, fuentesloic, hemant, Rossolson, Forl, thth, greg.cochard, arai, wahome, nmve, roryokane, kdex, dxcqcv, Enaldi, uxitten, oksana-khristenko, muhammadghazali, Notary_Dash, samuele-artuso, papb, isonic, chalkers, Jib, clintonbloodworth, MForMarlon, deveedutta, vitaly-zdanevich, crathmel, tarungarg546, kentcdodds, alnorris, gportioli, Pumbaa80, mgwhitfield, tschaub, Sheppy, brassington, danielsgroves, jandem, Waldo, Ugoku, zhiyelee, ydaniv, HugoDaniel, jpmedley, Nickolay, sdtsui, foxbrush, sanderd17, teoli, BraulioVM, P0lip, RichardLitt, TJJFV, claudepache, Martii, ziyunfei, BlindWanderer, Meghraj, systemovich, evilpie, ChaitanyaGSNR, Skoua, ethertank, WebReflection, dbruant, Jesse

 Last updated by:martian2049,

A recent thread on the r-help mailing list raises a common question for beginning R users: should you use = (equals) or <- (back arrow) for assignments?  In R, both of the following statements have the effect of assigning the value 3 to the variable x:

x = 3

x <- 3

So if they have the same effect, does it matter which you use?

A little history before we continue: when the R language (and S before it) was first created, <- was the only choice of assignment operator.  This is a hangover from the language APL, where the arrow notation was used to distinguish assignment (assign the value 3 to x) from equality (is x equal to 3?). (Professor Ripley reminds me that on APL keyboards there was an actual key on the keyboard with the arrow symbol on it, so the arrow was a single keystroke back then. The same was true of the AT&T terminals first used for the predecessors of S as described in the Blue Book.) However many modern languages (such as C, for example) use = for assignment, so beginners using R often found the arrow notation cumbersome, and were prone to use = by mistake.  But R uses = for yet another purpose: associating function arguments with values (as in pnorm(1, sd=2), to set the standard deviation to 2).

To make things easier for new users familiar with languages like C, R added the capability in 2001 to also allow = be used as an assignment operator, on the basis that the intent (assignment or association) is usually clear by context.  So,

x = 3

clearly means "assign 3 to x", whereas

f(x = 3)

clearly means "call function f, setting the argument x to 3".

There is one case where ambiguity might occur: if you wanted to assign a variable during a function call. The only way to do this in modern versions of R is:

f(x <- 3)

which means "assign 3 to x, and call f with the first argument set to the value 3".  This is a contrived example though, and never really occurs in real-world programming.  [UPDATE: In fact, constructs like this are best avoided for reasons given in the comments below.]

So, back to the original question: should you use = or <- for assignment?  It really boils down to preference.  Many people are more used to using = for assignment, and it's one less keystroke if you want to save on typing.  On the other hand, many R traditionalists prefer <- for clarity, and if you plan to share or publish your code, other might find code using = for assignment hard to read. Personally, I prefer the arrow notation, with a space on either side.

So, long story short: it's really up to you.

[Update Sep 2 2011: Added link to developer page for = assignment.] 

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *