aboutsummaryrefslogtreecommitdiff
path: root/files/ko/web/javascript/reference/functions/애로우_펑션/index.html
blob: 02dc0d55e48ed90a612e42c05e7ca6de4fa5cc18 (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
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
---
title: 화살표 함수
slug: Web/JavaScript/Reference/Functions/애로우_펑션
tags:
  - ECMAScript6
  - Functions
  - Intermediate
  - JavaScript
  - Reference
translation_of: Web/JavaScript/Reference/Functions/Arrow_functions
---
<div>{{jsSidebar("Functions")}}</div>

<p>화살표 함수 표현(<strong>arrow function expression</strong>)은 <a href="/ko/docs/Web/JavaScript/Reference/Operators/function" title="function expressions">function 표현</a>에 비해 구문이 짧고  자신의 <a href="/ko/docs/Web/JavaScript/Reference/Operators/this">this</a>, <a href="/ko/docs/Web/JavaScript/Reference/Functions/arguments">arguments</a>, <a href="/ko/docs/Web/JavaScript/Reference/Operators/super">super</a> 또는 <a href="/ko/docs/Web/JavaScript/Reference/Operators/new.target">new.target</a>을 바인딩 하지 않습니다. 화살표 함수는 항상 <a href="/ko/docs/Web/JavaScript/Reference/Global_Objects/Function/name" title="anonymous">익명</a>입니다. 이  함수 표현은 메소드 함수가 아닌 곳에 가장 적합합니다. 그래서 생성자로서 사용할 수 없습니다.</p>

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

<h2 id="구문">구문</h2>

<h3 id="기본_구문">기본 구문</h3>

<pre class="syntaxbox notranslate"><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>
// 다음과 동일함:  =&gt; { return expression; }

// 매개변수가 하나뿐인 경우 괄호는 선택사항:
<em>(singleParam)</em> <strong>=&gt; {</strong> <em>statements</em> <strong>}</strong>
<em>singleParam</em> <strong>=&gt;</strong> { <em>statements }</em>

// 매개변수가 없는 함수는 괄호가 필요:
<strong>() =&gt; {</strong> <em>statements</em> <strong>}</strong></pre>

<h3 id="고급_구문">고급 구문</h3>

<pre class="syntaxbox notranslate">// 객체 리터럴 표현을 반환하기 위해서는 함수 본문(body)을 괄호 속에 넣음:
<em>params</em> =&gt; ({<em>foo: bar</em>})

// <a href="/ko/docs/Web/JavaScript/Reference/Functions/rest_parameters" title="Rest parameter">나머지 매개변수</a><a href="/ko/docs/Web/JavaScript/Reference/Functions/Default_parameters" title="Default parameter">기본 매개변수</a>를 지원함
(<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="/ko/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment" title="Destructuring">구조분해할당</a>도 지원됨
var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) =&gt; a + b + c;
f();  // 6
</pre>

<p>상세한 구문 예는 <a href="http://wiki.ecmascript.org/doku.php?id=harmony:arrow_function_syntax">여기</a>에서 볼 수 있습니다.</p>

<h2 id="설명">설명</h2>

<p><a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">Hacks 블로그 "ES6 In Depth: Arrow functions" 포스트</a> 참조.</p>

<p>화살표 함수 도입에 영향을 준 두 요소: 보다 짧아진 함수 및  <code>바인딩하지 않은 this.</code></p>

<h3 id="짧은_함수">짧은 함수</h3>

<p>일부 함수 패턴에서는, 짧은 함수가 환영받습니다. 비교해 보세요:</p>

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

// 이 문장은 배열을 반환함: [8, 6, 7, 9]
elements.<a href="https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(function(element) {
  return element.length;
});

// 위의 일반적인 함수 표현은 아래 화살표 함수로 쓸 수 있다.
elements.map((element) =&gt; {
  return element.length;
}); // [8, 6, 7, 9]

// 파라미터가 하나만 있을 때는 주변 괄호를 생략할 수 있다.
elements.<a href="https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(element =&gt; {
  return element.length;
}); // [8, 6, 7, 9]

// 화살표 함수의 유일한 문장이 'return'일 때 'return'과
// 중괄호({})를 생략할 수 있다.
elements.map(element =&gt; element.length); // [8, 6, 7, 9]

// 이 경우 length 속성만 필요하므로 destructuring 매개변수를 사용할 수 있다.
// 'length'는 우리가 얻고자 하는 속성에 해당하는 반면,
// lengthFooBArX'는 변경 가능한 변수의 이름일 뿐이므로
// 원하는 유효한 변수명으로 변경할 수 있다.
elements.<a href="https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(({ length: lengthFooBArX }) =&gt; lengthFooBArX); // [8, 6, 7, 9]

// destructuring 파라미터 할당도 아래와 같이 작성할 수 있습니다.
// 이 예에서 정의한 객체내의 'length'에 값을 지정하지 않은 점에 주목하세요. 대신, "length" 변수의
// 리터럴 이름은 우리가 해당 객체에서 꺼내오고 싶은 속성이름 자체로 사용됩니다.
elements.<a href="https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a>(({ length }) =&gt; length); // [8, 6, 7, 9] </pre>

<h3 id="바인딩_되지_않은_this">바인딩 되지 않은 <code>this</code></h3>

<p>화살표 함수가 나오기 전까지는, 모든 새로운 함수는, 어떻게 그 함수가 호출되는지에 따라  자신의 <code><a href="/ko/docs/Web/JavaScript/Reference/Operators/this">this</a></code> 값을 정의했습니다:</p>

<ul>
 <li>이 함수가 생성자인 경우는 새로운 객체</li>
 <li><a href="/ko/docs/Web/JavaScript/Reference/Strict_mode" title="strict mode">엄격 모드</a> 함수 호출에서는 <code>undefined</code> </li>
 <li>함수가 "객체 메서드"로서 호출된 경우 문맥 객체</li>
 <li>등등</li>
</ul>

<p>이는 객체 지향 스타일로 프로그래밍할 때 별로 좋지않습니다.</p>

<pre class="brush: js notranslate">function Person() {
  // Person() 생성자는 `this`를 자신의 인스턴스로 정의.
  this.age = 0;

  setInterval(function growUp() {
    // 비엄격 모드에서, growUp() 함수는 `this`를
    // 전역 객체로 정의하고, 이는 Person() 생성자에
    // 정의된 `this`와 다름.
    this.age++;
  }, 1000);
}

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

<p>ECMAScript 3/5 에서는, 이 문제를 <code>this</code> 값을 폐쇄될 수 있는 (비전역) 변수에 할당하여 해결했습니다.</p>

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

  setInterval(function growUp() {
    // 콜백은  `that` 변수를 참조하고 이것은 값이 기대한 객체이다.
    that.age++;
  }, 1000);
}</pre>

<p>이렇게 하는 대신에, <a href="/ko/docs/Web/JavaScript/Reference/Global_Objects/Function/bind" title="bound function">바인딩한 함수</a>는 적절한 <code>this</code> 값이 <code>growUp()</code> 함수에 전달될 수 있도록 생성될 수 있습니다.</p>

<p>화살표 함수는 자신의 <code>this</code>가 없습니다.  대신 화살표 함수를 둘러싸는 렉시컬 범위(lexical scope)의 <code>this</code>가 사용됩니다; 화살표 함수는 일반 변수 조회 규칙(normal variable lookup rules)을 따릅니다. 때문에 현재 범위에서 존재하지 않는 <code>this</code>를 찾을 때, 화살표 함수는 바로 바깥 범위에서 <code>this</code>를 찾는것으로 검색을 끝내게 됩니다.</p>

<p>따라서 다음 코드에서 <code>setInterval</code>에 전달 된 함수 내부의 <code>this</code><code>setInterval</code>을 포함한 function의 <code>this</code>와 동일한 값을 갖습니다.</p>

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

  setInterval(() =&gt; {
    this.age++; // |this|는 Person 객체를 참조
  }, 1000);
}

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

<h4 id="엄격_모드와의_관계">엄격 모드와의 관계</h4>

<p><code>this</code>가 렉시컬(lexical, 정적)임을 감안하면, <code>this</code>에 관한 <a href="/ko/docs/Web/JavaScript/Reference/Strict_mode" title="strict mode">엄격 모드</a> 규칙은 그냥 무시됩니다.</p>

<pre class="notranslate">var f = () =&gt; { 'use strict'; return this; };
f() === window; // 혹은 전역객체</pre>

<p>엄격 모드의 나머지 규칙은 평소대로 적용합니다.</p>

<p><strong>CORRECTION: START</strong></p>

<p>NOTE: the previous statement seems false.</p>

<p>Strict mode should prevent creating global variables when assigning to an undeclared identifier in a function.</p>

<p>This code sample using Chrome 81 demonstrates that arrow functions allow the creation of global variables in such situations (both for a concise body and for a normal function body):</p>

<pre class="notranslate">&gt; f1 = x =&gt; { y = x; console.log(`x: ${x}, y: ${y}`); return x + 1; }
x =&gt; { y = x; console.log(`x: ${x}, y: ${y}`); return x + 1; }

&gt; y
VM51587:1 Uncaught ReferenceError: y is not defined
    at &lt;anonymous&gt;:1:1
(anonymous) @ VM51587:1

&gt; f1(3)
VM51533:1 x: 3, y: 3
4

&gt; y
3

&gt; f2 = x =&gt; { 'use strict'; z = x; console.log(`x: ${x}, z: ${z}`); return x + 1; }
x =&gt; { 'use strict'; z = x; console.log(`x: ${x}, z: ${z}`); return x + 1; }

&gt; z
VM51757:1 Uncaught ReferenceError: z is not defined
    at &lt;anonymous&gt;:1:1
(anonymous) @ VM51757:1

&gt; f2(4)
VM51712:1 Uncaught ReferenceError: z is not defined
    at f2 (&lt;anonymous&gt;:1:29)
    at &lt;anonymous&gt;:1:1
f2 @ VM51712:1
(anonymous) @ VM51800:1

&gt; f3 = x =&gt; (z1 = x + 1)
x =&gt; (z1 = x + 1)

&gt; z1
VM51891:1 Uncaught ReferenceError: z1 is not defined
    at &lt;anonymous&gt;:1:1
(anonymous) @ VM51891:1

&gt; f3(10)
11

&gt; z1
11
</pre>

<p>f2 illustrates that when explicitly setting the arrow function to apply strict mode, it does throw an error when attempting to assign an undeclared variable.</p>

<p>https://www.ecma-international.org/ecma-262/10.0/index.html#sec-strict-mode-code</p>

<p>https://www.ecma-international.org/ecma-262/10.0/index.html#sec-arrow-function-definitions-runtime-semantics-evaluation</p>

<p><strong>CORRECTION: END</strong></p>

<h4 id="call_또는_apply를_통한_피호출">call 또는 apply를 통한 피호출</h4>

<p>화살표 함수에서는 <code>this가 </code> 바인딩되지 않았기 때문에, <code>call()</code> 또는 <code>apply()</code> 메서드는  인자만 전달 할 수 있습니다. this는 무시됩니다.</p>

<pre class="brush: js notranslate">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));         // 이는 2가 콘솔에 출력될 것임
console.log(adder.addThruCall(1)); // 이도 2가 콘솔에 출력될 것임</pre>

<h3 id="바인딩_되지_않은_arguments">바인딩 되지 않은 <code>arguments</code></h3>

<p>화살표 함수는 <a href="/ko/docs/Web/JavaScript/Reference/Functions/arguments"><code>arguments</code> 객체</a>를 바인드 하지 않습니다.  때문에, <code>arguments는</code>  그저 둘러싸는 범위(scope) 내 이름에 대한 참조입니다.</p>

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

arr(); // 1

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

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

<p>화살표 함수는 자신의 <code>arguments</code> 객체가 없지만, 대부분의 경우에 <a href="/ko/docs/Web/JavaScript/Reference/Functions/rest_parameters" title="rest parameters">나머지 매개변수</a>가 좋은 대안입니다:</p>

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

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

<h3 id="메소드로_사용되는_화살표_함수">메소드로 사용되는 화살표 함수</h3>

<p>이야기 했듯이, 화살표 함수 표현은 메소드 함수가 아닌 형태로 사용 할 수 있습니다. 메소드로 사용하려고 한면 무슨일이 발생하는지 봅시다.</p>

<pre class="brush: js notranslate"><code>'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 {...}</code>
</pre>

<p>화살표 함수는 자신의 this를 가지고("bind" 바인드)있지 않습니다.{{jsxref("Object.defineProperty()")}}</p>

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

<h3 id="new_연산자_사용"><code>new</code> 연산자 사용</h3>

<p>화살표 함수는 생성자로서 사용될 수 없으며 <code>new</code>와 함께 사용하면 오류가 발생합니다.</p>

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

<h3 id="prototype_속성_사용"><code>prototype</code> 속성 사용</h3>

<p>화살표 함수는 <code>prototype</code> 속성이 없습니다.</p>

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

<h3 id="yield_키워드_사용"><code>yield</code> 키워드 사용</h3>

<p><code><a href="/ko/docs/Web/JavaScript/Reference/Operators/yield">yield</a></code> 키워드는 화살표 함수의 본문(그 안에 더 중첩된 함수 내에서 허용한 경우를 제외하고)에 사용될 수 없습니다. 그 결과, 화살표 함수는 생성기(generator)로서 사용될 수 없습니다.</p>

<h3 id="함수_본문">함수 본문</h3>

<p>화살표 함수는 "concise 바디"든 보통 "block 바디"든 하나를 가질 수 있습니다.</p>

<div class="note">
<p>concise바디는 중괄호'{}'로 묶이지않은 한줄짜리 바디이고 block바디는 중괄호로 묶인 바디입니다. 보통 여러줄 쓸때 block바디를 사용합니다.</p>
</div>

<p>block바디는 자동으로 값을 반환하지 않습니다. <code>return</code>을 사용해서 값을 반환해야 합니다.</p>

<pre class="brush: js notranslate">var func = x =&gt; x * x;                  // concise 바디, 생략된 "return" 여기서는 x * x
var func = (x, y) =&gt; { return x + y; }; // block 바디, "return"이 필요
</pre>

<h3 id="객체_리터럴_반환">객체 리터럴 반환</h3>

<p>간결한 구문 <code>params =&gt; {object:literal}</code>을 사용한 객체 리터럴 반환은 예상대로 작동하지 않음을 명심하세요:</p>

<pre class="brush: js notranslate">var func = () =&gt; {  foo: 1  };
// func() 호출은 undefined를 반환!

var func = () =&gt; {  foo: function() {}  };
// SyntaxError: function 문은 이름이 필요함</pre>

<p>이는 중괄호({}) 안 코드가 일련의 문(즉 <code>foo</code>는 라벨처럼 취급됩니다, 객체 리터럴 내 키가 아니라)으로 파싱(parse, 구문 분석)되기 때문입니다.</p>

<p>객체 리터럴를 괄호로 감싸는 것을 기억하세요:</p>

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

<h3 id="줄바꿈">줄바꿈</h3>

<p>화살표 함수는 파라메터와 화살표 사이에 개행 문자를 포함 할 수 없습니다.</p>

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

<p>하지만, 보기 좋은 코드를 유지하고 싶다면, 아래에 보는 것처럼 괄호나 개행을 둠으로써 이를 수정할 수 있습니다.</p>

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

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

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

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

// SyntaxError가 발생하지 않습니다.</code></pre>

<h3 id="파싱순서">파싱순서</h3>

<p>화살표 함수 내의 화살표는 연산자가 아닙니다. 그러나 화살표 함수는 평범한 함수와 비교했을 때 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence">operator precedence</a>와 다르게 반응하는 특별한 파싱룰을 가지고 있습니다.</p>

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

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

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

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

<h2 id="다른_예">다른 예</h2>

<h3 id="기본_사용법">기본 사용법</h3>

<pre class="brush: js notranslate"><code>// </code> empty 화살표 함수는 undefined를 반환 <code>
let empty = () =&gt; {};

(() =&gt; 'foobar')();
// "foobar" 반환
// (this is an Immediately Invoked Function Expression

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]

// 더 간결한 promise 체인
promise.then(a =&gt; {
  // ...
}).then(b =&gt; {
  // ...
});

// 매개변수가 없는 경우에도 더 읽기 쉬움
setTimeout( () =&gt; {
  console.log('I happen sooner');
  setTimeout( () =&gt; {
    // deeper code
    console.log('I happen later');
  }, 1);
}, 1);</code></pre>

<h2 id="스펙">스펙</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="브라우저_호환성">브라우저 호환성</h2>

<div class="hidden">
<p><span style="">The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out </span><a href="https://github.com/mdn/browser-compat-data" style="">https://github.com/mdn/browser-compat-data</a><span style=""> and send us a pull request.</span></p>
</div>

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

<h2 id="참조">참조</h2>

<ul>
 <li><a href="https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/">Hacks 블로그 "ES6 In Depth: Arrow functions" 포스트</a></li>
</ul>