diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:42:17 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:42:17 -0500 |
commit | da78a9e329e272dedb2400b79a3bdeebff387d47 (patch) | |
tree | e6ef8aa7c43556f55ddfe031a01cf0a8fa271bfe /files/ko/web/javascript/reference/functions/애로우_펑션 | |
parent | 1109132f09d75da9a28b649c7677bb6ce07c40c0 (diff) | |
download | translated-content-da78a9e329e272dedb2400b79a3bdeebff387d47.tar.gz translated-content-da78a9e329e272dedb2400b79a3bdeebff387d47.tar.bz2 translated-content-da78a9e329e272dedb2400b79a3bdeebff387d47.zip |
initial commit
Diffstat (limited to 'files/ko/web/javascript/reference/functions/애로우_펑션')
-rw-r--r-- | files/ko/web/javascript/reference/functions/애로우_펑션/index.html | 465 |
1 files changed, 465 insertions, 0 deletions
diff --git a/files/ko/web/javascript/reference/functions/애로우_펑션/index.html b/files/ko/web/javascript/reference/functions/애로우_펑션/index.html new file mode 100644 index 0000000000..02dc0d55e4 --- /dev/null +++ b/files/ko/web/javascript/reference/functions/애로우_펑션/index.html @@ -0,0 +1,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>) => {</strong> <em>statements</em> <strong>}</strong> +<strong>(</strong><em>param1</em>, <em>param2</em>, …, <em>paramN</em><strong>) =></strong> <em>expression</em> +// 다음과 동일함: => { return expression; } + +// 매개변수가 하나뿐인 경우 괄호는 선택사항: +<em>(singleParam)</em> <strong>=> {</strong> <em>statements</em> <strong>}</strong> +<em>singleParam</em> <strong>=></strong> { <em>statements }</em> + +// 매개변수가 없는 함수는 괄호가 필요: +<strong>() => {</strong> <em>statements</em> <strong>}</strong></pre> + +<h3 id="고급_구문">고급 구문</h3> + +<pre class="syntaxbox notranslate">// 객체 리터럴 표현을 반환하기 위해서는 함수 본문(body)을 괄호 속에 넣음: +<em>params</em> => ({<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>) => { <em>statements</em> } +(<em>param1</em> <strong>= defaultValue1</strong>, <em>param2</em>, …, paramN <strong>= defaultValueN</strong>) => { <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}) => 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) => { + 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 => { + return element.length; +}); // [8, 6, 7, 9] + +// 화살표 함수의 유일한 문장이 'return'일 때 'return'과 +// 중괄호({})를 생략할 수 있다. +elements.map(element => 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 }) => 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 }) => 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(() => { + 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 = () => { '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">> f1 = x => { y = x; console.log(`x: ${x}, y: ${y}`); return x + 1; } +x => { y = x; console.log(`x: ${x}, y: ${y}`); return x + 1; } + +> y +VM51587:1 Uncaught ReferenceError: y is not defined + at <anonymous>:1:1 +(anonymous) @ VM51587:1 + +> f1(3) +VM51533:1 x: 3, y: 3 +4 + +> y +3 + +> f2 = x => { 'use strict'; z = x; console.log(`x: ${x}, z: ${z}`); return x + 1; } +x => { 'use strict'; z = x; console.log(`x: ${x}, z: ${z}`); return x + 1; } + +> z +VM51757:1 Uncaught ReferenceError: z is not defined + at <anonymous>:1:1 +(anonymous) @ VM51757:1 + +> f2(4) +VM51712:1 Uncaught ReferenceError: z is not defined + at f2 (<anonymous>:1:29) + at <anonymous>:1:1 +f2 @ VM51712:1 +(anonymous) @ VM51800:1 + +> f3 = x => (z1 = x + 1) +x => (z1 = x + 1) + +> z1 +VM51891:1 Uncaught ReferenceError: z1 is not defined + at <anonymous>:1:1 +(anonymous) @ VM51891:1 + +> f3(10) +11 + +> 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 => 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)); // 이는 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 = () => 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</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) => 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: () => 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: () => { + 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 = () => {}; +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 = () => {}; +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 => x * x; // concise 바디, 생략된 "return" 여기서는 x * x +var func = (x, y) => { return x + y; }; // block 바디, "return"이 필요 +</pre> + +<h3 id="객체_리터럴_반환">객체 리터럴 반환</h3> + +<p>간결한 구문 <code>params => {object:literal}</code>을 사용한 객체 리터럴 반환은 예상대로 작동하지 않음을 명심하세요:</p> + +<pre class="brush: js notranslate">var func = () => { foo: 1 }; +// func() 호출은 undefined를 반환! + +var func = () => { foo: function() {} }; +// SyntaxError: function 문은 이름이 필요함</pre> + +<p>이는 중괄호({}) 안 코드가 일련의 문(즉 <code>foo</code>는 라벨처럼 취급됩니다, 객체 리터럴 내 키가 아니라)으로 파싱(parse, 구문 분석)되기 때문입니다.</p> + +<p>객체 리터럴를 괄호로 감싸는 것을 기억하세요:</p> + +<pre class="brush: js notranslate">var func = () => ({ foo: 1 });</pre> + +<h3 id="줄바꿈">줄바꿈</h3> + +<p>화살표 함수는 파라메터와 화살표 사이에 개행 문자를 포함 할 수 없습니다.</p> + +<pre class="brush: js notranslate"><code>var func = (a, b, c) + => 1; +// SyntaxError: expected expression, got '=>'</code></pre> + +<p>하지만, 보기 좋은 코드를 유지하고 싶다면, 아래에 보는 것처럼 괄호나 개행을 둠으로써 이를 수정할 수 있습니다.</p> + +<pre class="notranslate">var func = (a, b, c) => + 1; + +var func = (a, b, c) => ( + 1 +); + +var func = (a, b, c) => { + return 1 +}; + +<code>var func = ( + a, + b, + c +) => 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 || () => {}; +// SyntaxError: invalid arrow-function arguments + +callback = callback || (() => {}); // ok</code> +</pre> + +<h2 id="다른_예">다른 예</h2> + +<h3 id="기본_사용법">기본 사용법</h3> + +<pre class="brush: js notranslate"><code>// </code> empty 화살표 함수는 undefined를 반환 <code> +let empty = () => {}; + +(() => 'foobar')(); +// "foobar" 반환 +// (this is an Immediately Invoked Function Expression + +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] + +// 더 간결한 promise 체인 +promise.then(a => { + // ... +}).then(b => { + // ... +}); + +// 매개변수가 없는 경우에도 더 읽기 쉬움 +setTimeout( () => { + console.log('I happen sooner'); + setTimeout( () => { + // 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> |