aboutsummaryrefslogtreecommitdiff
path: root/files/pt-pt/web/javascript/reference/functions/arrow_functions/index.html
blob: 1a2246534bac07228c6beab8928e294a952f3b9b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
---
title: Expressões da função "Seta"
slug: Web/JavaScript/Reference/Functions/Arrow_functions
translation_of: Web/JavaScript/Reference/Functions/Arrow_functions
original_slug: Web/JavaScript/Reference/Funcoes/Funcoes_seta
---
<div>{{jsSidebar("Functions")}}</div>

<p>Uma <strong>expressão da função seta</strong> é uma alternativa sintaticamente compacta a uma expressão de <a href="/pt-PT/docs/Web/JavaScript/Reference/Operadores/função">expressão de função</a> regular, embora sem as suas próprias associações às palavras-chave <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/this">this</a></code>, <code><a href="/en-US/docs/Web/JavaScript/Reference/Functions/arguments">arguments</a></code>, <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/super">super</a></code>, ou <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/new.target">new.target</a></code>. As expressões de função (<em>function</em>) de seta são inadequadas como métodos, e não podem ser utilziadas como construtores.</p>

<div>{{EmbedInteractiveExample("pages/js/functions-arrow.html")}}</div>

<h2 id="Sintaxe">Sintaxe</h2>

<h3 id="Basic_syntax">Basic syntax</h3>

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

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

// The parameter list for a function with no parameters should be written with a pair of parentheses.
() =&gt; { statements }
</pre>

<h3 id="Advanced_syntax">Advanced syntax</h3>

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

// <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
(param1, param2, ...rest) =&gt; { statements }
(param1 = defaultValue1, param2, …, paramN = defaultValueN) =&gt; {
statements }

// <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>

<h2 id="Descrição">Descrição</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: the need for shorter functions and the behavior of the <code>this</code> keyword.</p>

<h3 id="Funções_curtas">Funções curtas</h3>

<pre class="brush: js">var elements = [
  'Hydrogen',
  'Helium',
  'Lithium',
  'Beryllium'
];

// This statement returns the array: [8, 6, 7, 9]
elements.<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(function(element) {
  return element.length;
});

// The regular function above can be written as the arrow function below
elements.map((element) =&gt; {
  return element.length;
}); // [8, 6, 7, 9]

// When there is only one parameter, we can remove the surrounding parentheses
elements.<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(element =&gt; {
  return element.length;
}); // [8, 6, 7, 9]

// When the only statement in an arrow function is `return`, we can remove `return` and remove
// the surrounding curly brackets
elements.map(element =&gt; element.length); // [8, 6, 7, 9]

// 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.<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(({ length: lengthFooBArX }) =&gt; lengthFooBArX); // [8, 6, 7, 9]

// 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.<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(({ length }) =&gt; length); // [8, 6, 7, 9]
</pre>

<h3 id="No_separate_this">No separate <code>this</code></h3>

<p>Before arrow functions, every new function defined its own <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/this">this</a></code> value based on how the function was called:</p>

<ul>
 <li>A new object in the case of a constructor.</li>
 <li><code>undefined</code> in <a href="/en-US/docs/Web/JavaScript/Reference/Strict_mode">strict mode</a> function calls.</li>
 <li>The base object if the function was called as an "object method".</li>
 <li>etc.</li>
</ul>

<p>This proved to be less than ideal 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 (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();</pre>

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

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

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

<p>An arrow function does not have its own <code>this</code>. The <code>this</code> value of the enclosing lexical scope is used; arrow functions follow the normal variable lookup rules. So while searching for <code>this</code> which is not present in current scope, an arrow function ends up finding the <code>this</code> from its enclosing scope.</p>

<p>Thus, in the following code, the <code>this</code> within the function that is passed to <code>setInterval</code> has the same value as the <code>this</code> in the lexically enclosing function:</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> comes from the surrounding lexical context, <a href="/en-US/docs/Web/JavaScript/Reference/Strict_mode">strict mode</a> rules with regard to <code>this</code> are ignored.</p>

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

<p>All other strict mode rules apply normally.</p>

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

<p>Since arrow functions do not have their own <code>this</code>, the methods <code>call()</code> and <code>apply()</code> can only pass in parameters. Any <code>this</code> argument is ignored.</p>

<pre class="brush: js">var adder = {
  base: 1,

  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
    };

    return f.call(b, a);
  }
};

console.log(adder.add(1));         // This would log 2
console.log(adder.addThruCall(1)); // This would log 2 still</pre>

<h3 id="No_binding_of_arguments">No binding of <code>arguments</code></h3>

<p>Arrow functions do not have their own <a href="/en-US/docs/Web/JavaScript/Reference/Functions/arguments"><code>arguments</code> object</a>. Thus, in this example, <code>arguments</code> is simply a reference to the arguments of the enclosing scope:</p>

<pre class="brush: js">var arguments = [1, 2, 3];
var arr = () =&gt; arguments[0];

arr(); // 1

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

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

<p>In most cases, using <a href="/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters">rest parameters</a> is a good alternative to using an <code>arguments</code> object.</p>

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

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

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

<p>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:</p>

<pre class="brush: js">'use strict';

var obj = { // does not create a new scope
  i: 10,
  b: () =&gt; 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 {...}</pre>

<p>Arrow functions do not have their own <code>this</code>. 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); // undefined 'undefined' Window {...} (or the global object)
    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>

<pre class="brush: js">var Foo = () =&gt; {};
var foo = new Foo(); // TypeError: Foo is not a constructor</pre>

<h3 id="Use_of_prototype_property">Use of <code>prototype</code> property</h3>

<p>Arrow functions do not have a <code>prototype</code> property.</p>

<pre class="brush: js">var Foo = () =&gt; {};
console.log(Foo.prototype); // undefined
</pre>

<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> 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.</p>

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

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

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

<pre class="brush: js">var func = x =&gt; x * x;
// concise body 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 body syntax <code>params =&gt; {object:literal}</code> will not work as expected.</p>

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

var func = () =&gt; { foo: function() {} };
// 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>You must wrap the object literal in parentheses:</p>

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

<h2 id="Line_breaks">Line breaks</h2>

<p>An arrow function cannot contain a line break between its parameters and its arrow.</p>

<pre class="brush: js">var func = (a, b, c)
  =&gt; 1;
// SyntaxError: expected expression, got '=&gt;'</pre>

<p>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.</p>

<pre class="brush: js">var func = (a, b, c) =&gt;
  1;

var func = (a, b, c) =&gt; (
  1
);

var func = (a, b, c) =&gt; {
  return 1
};

var func = (
  a,
  b,
  c
) =&gt; 1;

// no SyntaxError thrown</pre>

<h2 id="Parsing_order">Parsing order</h2>

<p>Although the arrow in an arrow function is not an operator, arrow functions have special parsing rules that interact differently with <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence">operator precedence</a> compared to regular functions.</p>

<pre class="brush: js">let callback;

callback = callback || function() {}; // ok

callback = callback || () =&gt; {};
// SyntaxError: invalid arrow-function arguments

callback = callback || (() =&gt; {});    // ok
</pre>

<h2 id="More_examples">More examples</h2>

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

(() =&gt; 'foobar')();
// Returns "foobar"
// (this is an <a href="/en-US/docs/Glossary/IIFE">Immediately Invoked Function Expression</a>)

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; {
  // ...
}).then(b =&gt; {
  // ...
});

// Parameterless arrow functions that are visually easier to parse
setTimeout( () =&gt; {
  console.log('I happen sooner');
  setTimeout( () =&gt; {
    // deeper code
    console.log('I happen later');
  }, 1);
}, 1);
</pre>

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

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">Specification</th>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-arrow-function-definitions', 'Arrow Function Definitions')}}</td>
  </tr>
 </tbody>
</table>

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

<div>


<p>{{Compat("javascript.functions.arrow_functions")}}</p>
</div>

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