import - JavaScript

import
======

정적 **`import`** 문은 다른 모듈에서 내보낸 바인딩을 가져올 때 사용합니다.

가져오는 모듈은 `"use strict"`의 존재 유무와 상관없이 무조건 엄격 모드입니다. HTML 안에 작성한 스크립트에서는 `import`를 사용할 수 없습니다.

함수형 구문을 가진 동적 \*\*`import()`\*\*도 있으며, `type="module"`을 필요로 하지 않습니다.

`<script>` 태그의 `nomodule` 속성을 사용해 하위호환성을 유지할 수 있습니다.

동적 가져오기는 모듈을 조건적으로 가져오고 싶거나, 필요할 때에만 가져올 때 유용합니다. 반면 초기 의존성을 불러올 때엔 정적 가져오기가 더 좋고, 정적 코드 분석 도구와 트리 셰이킹을 적용하기 쉽습니다.

구문
--

```js
    import defaultExport from "module-name";
    import \* as name from "module-name";
    import { export1 } from "module-name";
    import { export1 as alias1 } from "module-name";
    import { export1 , export2 } from "module-name";
    import { foo , bar } from "module-name/path/to/specific/un-exported/file";
    import { export1 , export2 as alias2 , [...] } from "module-name";
    import defaultExport, { export1 [ , [...] ] } from "module-name";
    import defaultExport, \* as name from "module-name";
    import "module-name";
    var promise = import("module-name");
```

`defaultExport`

모듈에서 가져온 기본 내보내기를 가리킬 이름.

`module-name`

가져올 대상 모듈. 보통, 모듈을 담은 `.js` 파일로의 절대 또는 상대 경로입니다. 번들러에 따라 확장자를 허용하거나, 필요로 할 수도 있으므로 작업 환경을 확인하세요. 따옴표와 쌍따옴표 문자열만 사용 가능합니다.

`name`

가져온 대상에 접근할 때 일종의 이름공간으로 사용할, 모듈 객체의 이름.

`exportN`

내보낸 대상 중 가져올 것의 이름.

`aliasN`

가져온 유명 내보내기를 가리킬 이름.

설명
--

`name` 파라미터는 export 되는 멤버를 받을 오브젝트의 이름입니다. `member` 파라미터는 각각의 멤버를 지정하지만, `name` 파라미터는 모두를 가져옵니다. 모듈에서 name 은 멤버 대신 하나의 default 파라미터를 통해 export 하는 경우에도 동작할 수 있습니다. 다음의 명확한 예제 문법을 살펴봅시다.

모듈 전체를 가져옵니다. export 한 모든 것들을 현재 범위(스크립트 파일 하나로 구분되는 모듈 범위) 내에 `myModule` 로 바인딩되어 들어갑니다.

```js
import \* as myModule from "my-module.js";
```

모듈에서 하나의 멤버만 가져옵니다. 현재 범위 내에 `myMember` 이 들어갑니다.

```js
import { myMember } from "my-module.js";
```

모듈에서 여러 멤버들을 가져옵니다. 현재 범위 내에 `foo` 와 `bar` 이 들어갑니다.

```js
import { foo, bar } from "my-module.js";
```

멤버를 가져올 때 좀 더 편리한 별명을 지정해줍니다. 현재 범위 내에 `shortName` 이 들어갑니다.

```js
import { reallyReallyLongModuleMemberName as shortName } from "my-module.js";
```

모듈에서 여러 멤버들을 편리한 별명을 지정하며 가져옵니다.

```js
import {
  reallyReallyLongModuleMemberName as shortName,
  anotherLongModuleName as short,
} from "my-module.js";
```

어떠한 바인딩 없이 모듈 전체의 사이드 이펙트만 가져옵니다.

```js
import "my-module.js";
```

### 기본값 가져오기

default export 를 통해 내보낸 것을 기본값으로 가져올 수 있습니다. (object, function, class 등). export 와 상반된 `import` 명령어를 통해 기본값을 가져오는 것이 가능합니다.

기본값으로 바로 가져오는 가장 간단한 버전:

```js
import myModule from "my-module.js";
```

위와 함께 기본 구문도 같이 사용할 수 있습니다 (namespace 가져오기 또는 이름 지정하여 가져오기). 이러한 경우, 기본값 가져오는 부분을 먼저 선언해야 할 것입니다. 예를 들어:

```js
import myDefault, \* as myModule from "my-module.js";
// myModule used as a namespace
```

또는

```js
import myDefault, { foo, bar } from "my-module.js";
// specific, named imports
```

예제
--

AJAX JSON 리퀘스트 처리를 돕는 보조 파일을 가져옵니다.

```js
// --file.js--
function getJSON(url, callback) {
  let xhr = new XMLHttpRequest();
  xhr.onload = function () {
    callback(this.responseText);
  };
  xhr.open("GET", url, true);
  xhr.send();
}

export function getUsefulContents(url, callback) {
  getJSON(url, (data) => callback(JSON.parse(data)));
}

// --main.js--
import { getUsefulContents } from "file.js";
getUsefulContents("http://www.example.com", (data) => {
  doSomethingUseful(data);
});
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-imports |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `export`
* Previewing ES6 Modules and more from ES2015, ES2016 and beyond
* ES6 in Depth: Modules, Hacks blog post by Jason Orendorff
* Axel Rauschmayer's book: "Exploring JS: Modules"


let - JavaScript

let
===

**`let`** 명령문은 블록 스코프의 범위를 가지는 지역 변수를 선언하며, 선언과 동시에 임의의 값으로 초기화할 수도 있습니다.

시도해보기
-----

구문
--

```js
let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]];
```

### 매개변수

`nameN`

변수 이름. 모두 유효한 JavaScript 식별자여야 합니다.

`valueN` Optional

각각의 변수 선언에 대해, 유효한 JavaScript 표현식을 지정해 변수의 초기 값을 지정할 수 있습니다.

이 구문 대신 구조 분해 할당을 사용해서 변수를 선언할 수도 있습니다.

```js
let { bar } = foo; // foo = { bar: 10, baz: 12 };
/\* 10의 값을 가진 'bar' 변수를 생성 \*/
```

설명
--

`let`을 사용하면 블록 명령문이나 `let`을 사용한 표현식 내로 범위가 제한되는 변수를 선언할 수 있습니다. 이는 `let`이 `var` 키워드와 다른 점으로, `var`는 변수를 블록을 고려하지 않고 현재 함수 (또는 전역 스코프) 어디에서나 접근할 수 있는 변수를 선언합니다. 또한 `let`은 파서가 구문을 평가해야만 변수를 값으로 초기화(아래 참고)한다는 점도 `var`와 다릅니다.

`const`와 마찬가지로 `let` 역시 전역 범위 선언에 사용(최상위 스코프 선언)해도 `window` 객체에 새로운 속성을 추가하지 않습니다.

왜 키워드의 이름이 "**let**"이 됐는지에 대한 설명은 여기서 읽을 수 있습니다.

**참고:** `let` 변수가 가진 다양한 문제는, `let` 변수 선언을 현재 스코프의 맨 위에서 수행해서 피할 수 있습니다.
 (가독성에 영향을 줄 수 있습니다)

예제
--

### 스코프 규칙

`let`으로 선언한 변수는 자신을 선언한 블록과 모든 하위 블록을 스스로의 스코프로 가집니다. 이런 점에서는 `let`이 `var`와 유사합니다. 그러나 둘의 중요한 차이는, `var`의 경우 스코프가 '자신을 선언한 블록'이 아니라, 자신의 선언을 포함하는 함수라는 점입니다.

```js
function varTest() {
  var x = 1;
  if (true) {
    var x = 2; // 같은 변수!
    console.log(x); // 2
  }
  console.log(x); // 2
}

function letTest() {
  let x = 1;
  if (true) {
    let x = 2; // 다른 변수
    console.log(x); // 2
  }
  console.log(x); // 1
}
```

프로그램 최상위에서 사용할 경우 `var`는 전역 객체에 속성을 추가하지만 `let`은 추가하지 않습니다.

```js
var x = "global";
let y = "global";
console.log(this.x); // "global"
console.log(this.y); // undefined
```

### 비공개 멤버 모사

생성자와 `let`을 함께 사용하면 클로저를 사용하지 않아도 비공개 멤버를 나타낼 수 있습니다.

```js
var Thing;

{
  let privateScope = new WeakMap();
  let counter = 0;

  Thing = function () {
    this.someProperty = "foo";

    privateScope.set(this, {
      hidden: ++counter,
    });
  };

  Thing.prototype.showPublic = function () {
    return this.someProperty;
  };

  Thing.prototype.showPrivate = function () {
    return privateScope.get(this).hidden;
  };
}

console.log(typeof privateScope);
// "undefined"

var thing = new Thing();

console.log(thing);
// Thing {someProperty: "foo"}

thing.showPublic();
// "foo"

thing.showPrivate();
// 1
```

클로저를 사용하면 `var`를 써도 위와 동일한 은닉 패턴을 구현할 수 있습니다. 그러나 이 경우, 위 코드와 같은 단순 블록 스코프를 사용할 수 없으며 함수 스코프(보통 모듈 패턴의 IIFE)가 필요합니다.

### 재선언

같은 변수를 같은 함수나 블록 스코프 안에서 다시 선언하려고 시도하면 `SyntaxError`가 발생합니다.

```js
if (x) {
  let foo;
  let foo; // SyntaxError
}
```

`switch` (en-US) 명령문에는 블록이 하나밖에 없으므로 이 오류를 자주 마주칠 수 있습니다.

```js
let x = 1;
switch (x) {
  case 0:
    let foo;
    break;

  case 1:
    let foo; // 재선언으로 인한 SyntaxError
    break;
}
```

그러나 분기에 블록을 배치하면 블록 스코프도 생성하므로 재선언으로 인한 오류가 발생하지 않습니다.

```js
let x = 1;

switch (x) {
  case 0: {
    let foo;
    break;
  }
  case 1: {
    let foo;
    break;
  }
}
```

### 시간상 사각지대

`let` 변수는 초기화하기 전에는 읽거나 쓸 수 없습니다(선언 구문에 초기 값을 지정하지 않은 경우 `undefined`로 초기화함). 초기화 전에 접근을 시도하면 `ReferenceError`가 발생합니다.

**참고:** `var` 변수와 다른 점으로, `var`의 경우 선언 전에 접근할 시 `undefined`입니다.

변수 스코프의 맨 위에서 변수의 초기화 완료 시점까지의 변수는 "시간상 사각지대"(Temporal Dead Zone, TDZ)에 들어간 변수라고 표현합니다.

```js
function do\_something() {
  console.log(bar); // undefined
  console.log(foo); // ReferenceError
  var bar = 1;
  let foo = 2;
}
```

"시간상" 사각지대인 이유는, 사각지대가 코드의 작성 순서(위치)가 아니라 코드의 실행 순서(시간)에 의해 형성되기 때문입니다. 예컨대 아래 코드의 경우 `let` 변수 선언 코드가 그 변수에 접근하는 함수보다 아래에 위치하지만, 함수의 호출 시점이 사각지대 밖이므로 정상 동작합니다.

```js
{
  // TDZ가 스코프 맨 위에서부터 시작
  const func = () => console.log(letVar); // OK

  // TDZ 안에서 letVar에 접근하면 ReferenceError

  let letVar = 3; // letVar의 TDZ 종료
  func(); // TDZ 밖에서 호출함
}
```

#### TDZ와 `typeof`

`typeof` 연산자를 TDZ 내의 `let` 변수에 사용해도 `ReferenceError`가 발생합니다.

```js
console.log(typeof i); // ReferenceError
let i = 10;
```

선언조차 하지 않은 변수, 또는 `undefined`를 값으로 가진 변수와 다른 점입니다.

```js
console.log(typeof undeclaredVariable); // undefined 출력
```

#### 어휘적 스코프와 결합한 TDZ

아래 코드는 주석으로 표기한 지점에서 `ReferenceError`가 발생합니다.

```js
function test() {
  var foo = 33;
  if (foo) {
    let foo = foo + 55; // ReferenceError
  }
}
test();
```

바깥 스코프의 `var foo`가 값을 가지므로 `if` 블록 또한 평가됩니다. 그러나 어휘적 스코프로 인해, `var foo`의 값은 블록 내에서 사용할 수 없습니다. 이곳의 `foo` 식별자는 `let foo`를 가리키기 때문입니다. 따라서 `(foo + 55)` 표현식은 `let foo`의 초기화가 끝나지 않은, 즉 TDZ의 내부이며 `ReferenceError`가 발생하게 되는 것입니다.

아래와 같은 코드에서는 이 현상으로 인해 상당한 혼란을 겪을 수 있습니다. 반복문의 `let n of n.a`는 `for` 블록의 스코프에 속하므로, 식별자 `n.a`는 반복문 스스로가 선언(`let n`)하는 `n` 객체의 `a` 속성을 가리킵니다. 그리고 `n`의 선언 후 초기화가 아직 끝나지 않았으므로 `n.a`는 `let n`의 TDZ에 속합니다.

```js
function go(n) {
  // 이 n은 매개변수 n
  console.log(n); // Object {a: [1,2,3]}

  for (let n of n.a) {
    // ReferenceError
    console.log(n);
  }
}

go({ a: [1, 2, 3] });
```

### 기타 예제

블록 내에서 사용한 경우 `let`은 변수의 스코프를 해당 블록으로 제한합니다. `var`는 스코프를 함수로 제한한다는 차이에 주의하세요.

```js
var a = 1;
var b = 2;

if (a === 1) {
  var a = 11; // 전역 변수
  let b = 22; // if 블록 변수

  console.log(a); // 11
  console.log(b); // 22
}

console.log(a); // 11
console.log(b); // 2
```

그러나 `var`와 `let`을 아래와 같이 사용하면 `SyntaxError`입니다. 호이스팅으로 인해 `var`가 블록 최상단으로 끌어올려져, 변수 재선언을 하는 것과 같아지기 때문입니다.

```js
let x = 1;

{
  var x = 2; // 재선언으로 인한 SyntaxError
}
```

명세
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-let-and-const-declarations |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `var`
* `const`
* ES6 In
Depth: `let` and `const`
* You
Don't Know JS: Scope & Closures: Chapter 3: Function vs. Block Scope
* StackOverflow: What is the
Temporal Dead Zone?
* StackOverflow:
What is the difference between using `let` and `var`?


for await...of - JavaScript

for await...of
==============

**`for await...of`** 문은 동기 이터러블뿐만 아니라 비동기 이터러블 객체를 순환하는 루프를 생성합니다. 이 문은 비동기 함수 본문 내부 와 모듈 내부를 포함하여 `await`를 사용할 수 있는 맥락에서만 사용할 수 있습니다.

시도해보기
-----

구문
--

```js
for await (variable of iterable)
  statement
```

`variable`

반복할 때마다 시퀀스에서 값을 받습니다. `const`, `let`, 또는 `var`를 사용한 선언이거나, 할당 연산자의 대상일 수 있습니다. (예: 이전에 선언된 변수 또는 객체 속성) `var`로 선언된 변수는 루프에 대한 로컬이 아닙니다. 즉, 해당 변수는 `for await...of` 루프가 있는 동일한 범위에 있습니다.

`iterable`

비동기 이터러블 또는 동기 이터러블입니다. 루프가 작동하는 값 시퀀스의 소스입니다.

`statement`

반복할 때마다 실행할 명령문입니다. `variable`을 참조할 수 있습니다. 블록 문을 사용하여 여러 문을 실행할 수 있습니다.

설명
--

`for await...of` 루프가 이터러블을 반복할 때, 먼저 비동기 이터레이터를 반환하는 이터러블의 `[@@asyncIterator]()` (en-US) 메서드를 가져와 호출합니다. `@asyncIterator` 메서드가 없으면 동기 이터레이터를 반환하는 `[@@iterator]()` 메서드를 찾습니다. 그런 다음 반환된 동기 이터레이터는 `next()`, `return()`, 그리고 `throw()` 메서드에서 반환된 모든 객체를 이행되거나 거부된 프로미스로 래핑하여 비동기 이터레이터로 래핑합니다. `value` 속성도 프로미스인 경우 이행됩니다. 그런 다음 루프는 최종 비동기 이터레이터의 `next()` 메서드를 반복적으로 호출하고 반환된 프로미스를 await하며 변수에 할당할 일련의 `value`를 생성합니다.

`for await...of` 루프가 일찍 종료되면(예: `break` 문이 발생하거나 오류가 발생한 경우) 정리를 수행하기 위해 이터레이터의 `return()` 메서드가 호출됩니다. 반환된 프로미스는 루프가 종료되기 전에 await됩니다.

`for await...of`는 일반적으로 `for...of` 루프와 동일하게 기능하며 동일한 구문과 의미를 공유합니다. 아래의 몇 가지 차이점은 있습니다.

* `for await...of`는 동기와 비동기 이터러블 모두에서 작동하지만 `for...of`는 동기 이터러블에서만 작동합니다.
* `for await...of`는 비동기 함수 본문 내부와 모듈을 포함하여 `await`를 사용할 수 있는 컨텍스트에서만 사용할 수 있습니다. 이터러블이 동기인 경우에도 루프는 여전히 매 순회마다 반환 값을 await하므로 반복되는 프로미스의 언래핑으로 인해 실행 속도가 느려집니다.
* `iterable`이 프로미스를을 yield하는 동기 이터러블인 경우 `for await...of`는 일련의 이행된 값을 생성하는 반면 `for...of`는 일련의 프로미스를 생성합니다. (그러나 오류 처리와 정리에 주의하세요. 동기 이터러블과 제너레이터에 순회 참조.)
* `for await...of`의 경우 `variable`은 `async`가 식별자 일 수 있습니다(예: `for await(async of foo)`). `for...of`는 이를 금지합니다.
예제
--

### 비동기 이터러블 순회

비동기 이터러블 프로토콜을 명시적으로 구현하는 객체를 반복할 수도 있습니다.

```js
const LIMIT = 3;

const asyncIterable = {
  [Symbol.asyncIterator]() {
    let i = 0;
    return {
      next() {
        const done = i === LIMIT;
        const value = done ? undefined : i++;
        return Promise.resolve({ value, done });
      },
      return() {
        // 여긴 소비자가 루프 초기에 'break' 또는 'return'을 호출한 경우에 도달합니다.
        return { done: true };
      },
    };
  },
};

(async () => {
  for await (const num of asyncIterable) {
    console.log(num);
  }
})();
// 0
// 1
// 2
```

### 비동기 제너레이터 순회

비동기 제너레이터 함수의 반환 값은 비동기 이터러블 프로토콜을 준수하므로 `for await...of`를 사용하여 반복할 수 있습니다.

```js
async function\* asyncGenerator() {
  let i = 0;
  while (i < 3) {
    yield i++;
  }
}

(async () => {
  for await (const num of asyncGenerator()) {
    console.log(num);
  }
})();
// 0
// 1
// 2
```

`for await...of`를 사용하여 비동기 제너레이터를 반복하는 보다 구체적인 예제를 위해 API에서 데이터를 순회하는 것을 생각해 보겠습니다.

이 예제는 먼저 데이터 스트림에 대한 비동기 이터러블을 생성한 다음, 이를 사용하여 API 응답의 크기를 찾습니다.

```js
async function\* streamAsyncIterable(stream) {
  const reader = stream.getReader();
  try {
    while (true) {
      const { done, value } = await reader.read();
      if (done) return;
      yield value;
    }
  } finally {
    reader.releaseLock();
  }
}

// URL에서 데이터를 가져오고 비동기 제너레이터를 사용하여 응답 크기를 계산합니다.
async function getResponseSize(url) {
  const response = await fetch(url);
  // 응답 크기를 바이트 단위로 유지.
  let responseSize = 0;
  // for-await-of 루프. 비동기는 응답의 각 부분을 순회.
  for await (const chunk of streamAsyncIterable(response.body)) {
    // 총 응답 길이 증가.
    responseSize += chunk.length;
  }

  console.log(`Response Size: ${responseSize} bytes`); // "Response Size: 1071472"
  return responseSize;
}
getResponseSize("https://jsonplaceholder.typicode.com/photos");
```

### 동기 이터러블과 제너레이터 순회

`for await...of` 루프에서 동기 이터러블과 동기 제너레이터도 사용할 수 있습니다. 이 경우, 산출된 값을 루프 제어 변수에 할당하기 전에 내부적으로 await합니다.

```js
function\* generator() {
  yield 0;
  yield 1;
  yield Promise.resolve(2);
  yield Promise.resolve(3);
  yield 4;
}

(async () => {
  for await (const num of generator()) {
    console.log(num);
  }
})();
// 0
// 1
// 2
// 3
// 4

// for-of 루프와 비교

for (const numOrPromise of generator()) {
  console.log(numOrPromise);
}
// 0
// 1
// Promise { 2 }
// Promise { 3 }
// 4
```

**참고:** 동기 제너레이터에서 거부된 프로미스 yield에 유의하세요. 이 경우 `for await...of`는 거부된 프로미스를 처리할 때 throw를 하고, 해당 제너레이터의 `finally` 블록을 **호출하지 않습니다**. 이것은 할당된 일부 리소스를 `try/finally`로 해제해야 하는 경우에 바람직하지 않을 수 있습니다.

```js
function\* generatorWithRejectedPromises() {
  try {
    yield 0;
    yield 1;
    yield Promise.resolve(2);
    yield Promise.reject(3);
    yield 4;
    throw 5;
  } finally {
    console.log("called finally");
  }
}

(async () => {
  try {
    for await (const num of generatorWithRejectedPromises()) {
      console.log(num);
    }
  } catch (e) {
    console.log("caught", e);
  }
})();
// 0
// 1
// 2
// caught 3

// for-of 루프와 비교

try {
  for (const numOrPromise of generatorWithRejectedPromises()) {
    console.log(numOrPromise);
  }
} catch (e) {
  console.log("caught", e);
}
// 0
// 1
// Promise { 2 }
// Promise { <rejected> 3 }
// 4
// caught 5
// called finally
```

동기 제어레이터의 `finally` 블록을 항상 호출되게 만드려면, 루프의 적절한 형식(비동기 제너레이터의 경우 `for await...of`, 동기 제너레이터의 경우 `for...of`)을 사용하고 루프 내에서 명시적으로 yield된 프로미스를 await해야 합니다.

```js
(async () => {
  try {
    for (const numOrPromise of generatorWithRejectedPromises()) {
      console.log(await numOrPromise);
    }
  } catch (e) {
    console.log("caught", e);
  }
})();
// 0
// 1
// 2
// caught 3
// called finally
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-for-in-and-for-of-statements |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `Symbol.asyncIterator` (en-US)
* `for...of`


async function - JavaScript

async function
==============

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since April 2017.

* Learn more
* See full compatibility
* Report feedback
**`async function`** 선언은 `AsyncFunction`객체를 반환하는 하나의 비동기 함수를 정의합니다. 비동기 함수는 이벤트 루프를 통해 비동기적으로 작동하는 함수로, 암시적으로 `Promise`를 사용하여 결과를 반환합니다. 그러나 비동기 함수를 사용하는 코드의 구문과 구조는, 표준 동기 함수를 사용하는것과 많이 비슷합니다.

또한 async function expression을 사용해서 async function을 선언할 수 있습니다.

시도해보기
-----

Syntax
------

```js
    async function name([param[, param[, ... param]]]) {
        statements
    }
```

### 매개변수

`name`

함수의 이름.

`param` Optional

함수에게 전달되기 위한 인자의 이름.

`statements` Optional

함수 본문을 구성하는 내용. await 메커니즘이 사용될 수 있다.

Description
-----------

`async` 함수에는 `await`식이 포함될 수 있습니다. 이 식은 `async` 함수의 실행을 일시 중지하고 전달 된 `Promise`의 해결을 기다린 다음 `async` 함수의 실행을 다시 시작하고 완료후 값을 반환합니다.

>
> **Note:** `await` 키워드는 `async` 함수에서만 유효하다는 것을 기억하십시오. `async` 함수의 본문 외부에서 사용하면 SyntaxError가 발생합니다.
>
>
>

>
> **Note:** async/await함수의 목적은 사용하는 여러 promise의 동작을 동기스럽게 사용할 수 있게 하고, 어떠한 동작을 여러 promise의 그룹에서 간단하게 동작하게 하는 것이다. promise가 구조화된 callback과 유사한 것 처럼 `async/await` 또한 제네레이터(generator)와 프로미스(promise)를 묶는것과 유사하다.
>
>
>

`async` 함수는 항상 promise를 반환합니다. 만약 `async` 함수의 반환값이 명시적으로 promise가 아니라면 암묵적으로 promise로 감싸집니다.

예를 들어

```js
async function foo() {
  return 1;
}
```

위 코드는 아래와 같습니다.

```js
function foo() {
  return Promise.resolve(1);
}
```

`async` 함수의 본문은 0개 이상의 `await` 문으로 분할된 것으로 생각할 수 있습니다. 첫번째 `await` 문을 포함하는 최상위 코드는 동기적으로 실행됩니다. 따라서 `await` 문이 없는 `async` 함수는 동기적으로 실행됩니다. 하지만 `await` 문이 있다면 `async` 함수는 항상 비동기적으로 완료됩니다.

예를 들어

```js
async function foo() {
  await 1;
}
```

위 코드는 아래와 같습니다.

```js
function foo() {
  return Promise.resolve(1).then(() => undefined);
}
```

Examples
--------

### Simple example

```js
var resolveAfter2Seconds = function () {
  console.log("starting slow promise");
  return new Promise((resolve) => {
    setTimeout(function () {
      resolve(20);
      console.log("slow promise is done");
    }, 2000);
  });
};

var resolveAfter1Second = function () {
  console.log("starting fast promise");
  return new Promise((resolve) => {
    setTimeout(function () {
      resolve(10);
      console.log("fast promise is done");
    }, 1000);
  });
};

var sequentialStart = async function () {
  console.log("==SEQUENTIAL START==");

  // If the value of the expression following the await operator is not a Promise, it's converted to a resolved Promise.
  const slow = await resolveAfter2Seconds();
  console.log(slow);

  const fast = await resolveAfter1Second();
  console.log(fast);
};

var concurrentStart = async function () {
  console.log("==CONCURRENT START with await==");
  const slow = resolveAfter2Seconds(); // starts timer immediately
  const fast = resolveAfter1Second();

  console.log(await slow);
  console.log(await fast); // waits for slow to finish, even though fast is already done!
};

var stillConcurrent = function () {
  console.log("==CONCURRENT START with Promise.all==");
  Promise.all([resolveAfter2Seconds(), resolveAfter1Second()]).then(
    (messages) => {
      console.log(messages[0]); // slow
      console.log(messages[1]); // fast
    },
  );
};

var parallel = function () {
  console.log("==PARALLEL with Promise.then==");
  resolveAfter2Seconds().then((message) => console.log(message));
  resolveAfter1Second().then((message) => console.log(message));
};

sequentialStart(); // after 2 seconds, logs "slow", then after 1 more second, "fast"
// wait above to finish
setTimeout(concurrentStart, 4000); // after 2 seconds, logs "slow" and then "fast"
// wait again
setTimeout(stillConcurrent, 7000); // same as concurrentStart
// wait again
setTimeout(parallel, 10000); // trully parallel: after 1 second, logs "fast", then after 1 more second, "slow"
```

>
> **Warning:** `await` 와 `Promise#then`을 혼동하지 마세요. `sequentialStart` 에서, 첫 번째 `await`는 2초의 대기 시간을 갖고, 다시 두 번째 `await`에서 1초의 대기 시간을 갖습니다. 두 번째 타이머는 첫 번째 타이머가 완료될 때 까지 생성되지 않습니다. `concurrentStart` 에서, 두 타이머 모두 생성 된 다음 `await` 합니다. 타이머가 동시에 실행되고 있지만, `await` 호출은 여전히 연속적 실행중이므로, 두 번째 `await` 는 첫 번째 호출이 끝날 때 까지 대기합니다. 이렇게하면 3초가 아니라, 가장 느린 타이머에 필요한 2초가 필요합니다. `stillConcurrent` 에서도 `Promise.all` 을 사용하여 같은 일이 발생합니다. 두 개 이상의 프러미스를 동시에 wait 하고 싶다면, `Promise#then`을 사용하여 예제와 같이 `parallel` 를 수행할 수 있습니다.
>
>
>

### `async`함수를 사용한 promise chain 재작성

`Promise` 를 반환하는 API는 promise chain을 만들며 여러 파트의 함수로 나뉜다.
 아래 코드를 보자.

```js
function getProcessedData(url) {
  return downloadData(url) // returns a promise
    .catch((e) => {
      return downloadFallbackData(url); // returns a promise
    })
    .then((v) => {
      return processDataInWorker(v); // returns a promise
    });
}
```

위의 코드는 하나의 async함수로 아래와 같이 쓰여질 수도 있다.

```js
async function getProcessedData(url) {
  let v;
  try {
    v = await downloadData(url);
  } catch (e) {
    v = await downloadFallbackData(url);
  }
  return processDataInWorker(v);
}
```

위 예제에서는 return 구문에 await 구문이 없다는 것에 주목하자. 이는 async function의 반환값이 암묵적으로 `Promise.resolve`로 감싸지기 때문이다.

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-async-function-definitions |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

함께 보기
-----

* `async function expression`
* `AsyncFunction` object
* `await`
* "Decorating Async Javascript Functions" on "innolitics.com"


do...while - JavaScript

do...while
==========

**`do...while` 문은** 테스트 조건이 거짓으로 평가될 때까지 지정된 구문을 실행하는 루프를 만듭니다.
 단, 구문이 실행된 뒤에 테스트 조건이 평가됨으로 구문은 무조건 한 번은 실행됩니다.

시도해보기
-----

문법
--

```js
do {
  statement;
} while (condition);
```

`구문`

테스트 조건이 참일 때마다 한 번이상 실행되는 구문입니다. 만약 루프 내에서 여러 구문을 반복 실행 시키고 싶으시다면, 다음 명령을 사용합니다. block 구문을 활용하여 (`{ ... }`) 이런 식으로 그룹화합니다.

`조건식`

루프가 실행될 때마다 평가되는 식입니다. 만약 조건식이 참으로 평가되었다면, `구문` 이 다시 실행됩니다. 만약 조건식이 거짓으로 평가되었다면, JavaScript는 `do...while`. 구문 밑에 있는 구문들을 실행시킵니다.

예제
--

### `do...while`

예제에서 `do...while` 문은 적어도 한번 반복되고 i 변수가 5 보다 작을 때까지 실행됩니다.

```js
var result = "";
var i = 0;
do {
  i += 1;
  result += i + " ";
} while (i > 0 && i < 5);
// Despite i == 0 this will still loop as it starts off without the test

console.log(result);
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-do-while-statement |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `while`
* `for`


empty - JavaScript

empty
=====

**empty** 문은 JavaScript 아무것도 동작하지 않습니다.

시도해보기
-----

구문
--

```js
;
```

설명
--

empty statement은 JavaScript구문에 하나가 필요할 때 어떤 문도 실행되지 않을 것이라는 것을 나타내는 세미 콜론(;)입니다. 여러개의 문장을 원하지만 JavaScript는 block statement을 사용하여 하나만 허용하며 여러개의 문장을 하나로 결합합니다.

예제
--

빈 문은 루프 문과 함께 사용되기도합니다. 빈 루프 본문이있는 다음 예제를 참조하십시오.

```js
var arr = [1, 2, 3];

// Assign all array values to 0
for (i = 0; i < arr.length; arr[i++] = 0 /\* empty statement \*/);

console.log(arr);
// [0, 0, 0]
```

**참고:** 정상적인 세미 콜론을 구분하는 것이 그리 쉽지 않기 때문에, empty statement를 사용할 때는 의도적으로 주석을 달아주는것이 좋습니다. 다음 예 에서는 의도한대로 코드가 동작하지 않을것입니다. 아마도 killTheUniverse()를 if문 안에서 실행하고자 했던것 같습니다.

```js
if (condition);       // Caution, this "if" does nothing!
   killTheUniverse()  // So this always gets executed!!!
```

다른 예 : 중괄호 ({})가없는 `if...else` 문에서 `three`가 `true`이면 아무 일도 일어나지 않고 `four`를 건너 뛰고 else case의 launchRocket() 함수도 실행되지 않습니다.

```js
if (one) doOne();
else if (two) doTwo();
else if (three); // nothing here
else if (four)
  doFour();
else launchRocket();
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-empty-statement |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `Block statement`


debugger - JavaScript

debugger
========

**`debugger` 문**은 중단점 설정 등 현재 사용할 수 있는 디버그 기능을 호출합니다. 사용할 수있는 디버깅 기능이 없으면 아무런 동작도 하지 않습니다.

구문
--

```js
debugger;
```

예제
--

다음 예제에서는 함수가 호출 시 디버거를 활성화하도록 `debugger`를 삽입한 모습입니다.

```js
function potentiallyBuggyCode() {
  debugger;
  // 버그가 있을 것으로 생각하는 코드를 분석하거나, 한 단계씩 진행해보거나...
}
```

디버거가 활성화되면 디버거 문의 위치에서 실행이 일시중지됩니다. 스크립트 소스의 중단점과 비슷합니다.

![Paused at a debugger statement.](/ko/docs/Web/JavaScript/Reference/Statements/debugger/screen_shot_2014-02-07_at_9.14.35_am.png)

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-debugger-statement |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* JavaScript 디버깅
* Firefox 개발자 도구의 디버거


var - JavaScript

var
===

**`var`** 문은 변수를 선언하고, 선택적으로 초기화할 수 있습니다.

시도해보기
-----

구문
--

```js
    var varname1 [= value1 [, varname2 [, varname3 ... [, varnameN]]]];
```

`varnameN`

변수 이름. 어떤 유효한 식별자도 될 수 있습니다.

`valueN`

변수의 초기값. 어떤 유효한 표현도 될 수 있습니다.

설명
--

어디에 선언이 되어있든 간에 변수들은 어떠한 코드가 실행되기 전에 처리가 됩니다. var로 선언된 변수의 범위는 현재 실행 문맥인데, 그 문맥은 둘러싼 함수, 혹은 함수의 외부에 전역으로 선언된 변수도 될 수 있습니다.

선언된 변수들의 값 할당은 할당이 실행될 때 전역변수(이것은 전역 오브젝트의 프로퍼티가 됩니다)처럼 생성이 됩니다. 선언된 변수들과 선언되지 않은 변수들의 차이점은 다음과 같습니다:

1. 선언된 변수들은 변수가 선언된 실행 콘텍스트(execution context) 안에서 만들어집니다. 선언되지 않은 변수들은 항상 전역변수 입니다.

```js
function x() {
  y = 1; // strict 모드에서는 ReferenceError를 출력합니다.
  var z = 2;
}

x();

console.log(y); // 로그에 "1" 출력합니다.
console.log(z); // ReferenceError: z is not defined outside x를 출력합니다.
```

2. 선언된 변수들은 어떠한 코드가 실행되기 전에 만들어집니다. 선언되지 않은 변수들은 변수들을 할당하는 코드가 실행되기 전까지는 존재하지 않습니다.

```js
console.log(a); // ReferenceError를 출력합니다.
console.log("still going..."); // 결코 실행되지 않습니다.
```

```js
var a;
console.log(a); // 브라우저에 따라 로그에 "undefined" 또는 "" 출력합니다.
console.log("still going..."); // 로그에 "still going..." 출력합니다.
```

3. 선언된 변수들은 변수들의 실행 콘텍스트(execution context)의 프로퍼티를 변경되지 않습니다. 선언되지 않은 변수들은 변경 가능합니다. (e.g 삭제 될 수도 있습니다.)

```js
var a = 1;
b = 2;

delete this.a; // strict 모드에서는 TypeError를 출력합니다. 그렇지 않으면 자동적으로 실패합니다.
delete this.b;

console.log(a, b); // ReferenceError를 출력합니다.
// 'b' 프로퍼티는 삭제되었고, 어디에도 존재하지 않습니다.
```

이러한 세가지 다른점 때문에, 변수 선언 오류는 예기치않은 결과로 이어질 가능성이 높습니다. 그러므로 **함수 또는 전역 범위인지 여부와 상관없이, 항상 변수를 선언 하는 것을 추천합니다.** 그리고 ECMAScript 5 안에 strict mode (en-US), 선언되지 않은 변수에 할당하면 오류를 출력합니다.

### var 호이스팅(hoisting)

변수 선언들 (그리고 일반적인 선언)은 어느 코드가 실행 되기 전에 처리하기 때문에, 코드 안에서 어디서든 변수 선언은 최상위에 선언한 것과 동등합니다. 이것은 변수가 선언되기 전에 사용 될 수 있다는 것을 의미합니다. 변수 선언이 함수 또는 전역 코드의 상단에 이동하는 것과 같은 행동을 "호이스팅(hoisting)"이라고 불립니다.

```js
bla = 2;
var bla;
// ...

// 위 선언을 다음과 같이 암묵적으로 이해하면 됩니다:

var bla;
bla = 2;
```

이러한 이유로, 그들의 범위(전역 코드의 상단 그리고 함수 코드의 상단) 상단에 변수를 항상 선언하기를 권장합니다. 그러면 변수는 함수 범위 (지역)이 되며, 스코프 체인으로 해결될 것이 분명합니다.

예제
--

### 두 변수들의 선언 및 초기화

```js
var a = 0,
  b = 0;
```

### 단일 문자열 값으로 두 변수들 할당

```js
var a = "A";
var b = a;

// 다음과 같음:

var a,
  b = (a = "A");
```

순서에 유의:

```js
var x = y,
  y = "A";
console.log(x + y); // undefinedA
```

여기, x와 y는 어떠한 코드 실행하기 전에 선언되었다, 할당은 후에 발생하였다. "`x = y`"가 실행될 때, `y`는 존재하여 `ReferenceError를 출력하진 않고` 값은 '`undefined`' 입니다. 그래서, `x는` undefined 값이 할당 됩니다. 그리고나서, `y` 는 `'A'` 값이 할당 됩니다. 결과적으로, 첫번째 줄 이후에, `x === undefined && y === 'A'`, 이와 같은 결과가 됩니다.

### 다수의 변수들의 초기화

```js
var x = 0;

function f() {
  var x = (y = 1); // x는 지역변수로 선언됩니다. y는 아닙니다!
}
f();

console.log(x, y); // 0, 1
// x는 예상대로 전역이다
// y leaked outside of the function, though!
```

### 암묵적인 전역변수와 외부 함수 범위

암묵적인 전역변수가 될 것으로 보이는 변수는 함수 범위 밖에서 변수들을 참조할 수 있다.

```js
var x = 0; // x는 전역으로 선언되었고, 0으로 할당됩니다.

console.log(typeof z); // undefined, z는 아직 존재하지 않습니다.

function a() {
  // a 함수를 호출했을 때,
  var y = 2; // y는 함수 a에서 지역변수로 선언되었으며, 2로 할당됩니다.

  console.log(x, y); // 0 2

  function b() {
    // b 함수를 호출하였을때,
    x = 3; // 존재하는 전역 x값에 3을 할당, 새로운 전역 var 변수를 만들지 않습니다.
    y = 4; // 존재하는 외부 y값에 4를 할당, 새로운 전역 var 변수를 만들지 않습니다.
    z = 5; // 새로운 전역 z 변수를 생성하고 5를 할당 합니다.
  } // (strict mode에서는 ReferenceError를 출력합니다.)

  b(); // 호출되는 b는 전역 변수로 z를 생성합니다.
  console.log(x, y, z); // 3 4 5
}

a(); // 호출되는 a는 또한 b를 호출합니다.
console.log(x, z); // 3 5
console.log(typeof y); // undefined y는 function a에서 지역 변수입니다.
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-variable-statement |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `let`
* `const`


return - JavaScript

return
======

**`return` 명령문**은 함수 실행을 종료하고, 주어진 값을 함수 호출 지점으로 반환합니다.

시도해보기
-----

구문
--

```js
return [[expression]];
```

`expression`

반환할 값으로 사용할 표현식. 생략할 경우 `undefined`를 대신 반환합니다.

설명
--

함수 본문에서 `return` 명령문에 도달하면 함수의 실행은 그 지점에서 중단됩니다. 값을 제공한 경우 함수를 호출한 곳에 그 값을 반환합니다. 예를 들어, 다음 함수는 숫자 매개변수 `x`의 제곱을 반환합니다.

```js
function square(x) {
  return x \* x;
}
var demo = square(3);
// demo는 9
```

값을 명시하지 않으면 대신 `undefined`를 반환합니다.

다음 `return` 명령문 모두 함수 실행을 끊습니다.

```js
return;
return true;
return false;
return x;
return x + y / 3;
```

### 자동 세미콜론 삽입

`return` 명령문은 자동 세미콜론 삽입(ASI) (en-US)의 영향을 받습니다. `return` 키워드와 표현식 사이에는 줄바꿈 문자가 올 수 없습니다.

```js
return
a + b;
```

위 코드는 ASI로 인해 아래처럼 처리됩니다.

```js
return;
a + b;
```

콘솔이 "unreachable code after return statement" 경고를 출력할 것입니다.

문제를 해결하려면 괄호를 사용해 ASI를 방지해야 합니다.

```js
return a + b;
```

예제
--

### 함수 중단

함수는 `return`을 호출하는 지점에서 즉시 실행을 멈춥니다.

```js
function counter() {
  for (var count = 1; ; count++) {
    // 무한 반복
    console.log(count + "A"); // 5까지
    if (count === 5) {
      return;
    }
    console.log(count + "B"); // 4까지
  }
  console.log(count + "C"); // 절대 나타나지 않음
}

counter();

// 출력:
// 1A
// 1B
// 2A
// 2B
// 3A
// 3B
// 4A
// 4B
// 5A
```

### 함수 반환하기

클로저에 대해서도 더 알아보세요.

```js
function magic(x) {
  return function calc(x) {
    return x \* 42;
  };
}

var answer = magic();
answer(1337); // 56154
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-return-statement |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* 함수
* 클로저


export - JavaScript

export
======

**`export`** 문은 JavaScript 모듈에서 함수, 객체, 원시 값을 내보낼 때 사용합니다. 내보낸 값은 다른 프로그램에서 `import` 문으로 가져가 사용할 수 있습니다.

내보내는 모듈은 `"use strict"`의 존재 유무와 상관없이 무조건 엄격 모드입니다. `export` 문은 HTML 안에 작성한 스크립트에서는 사용할 수 없습니다.

구문
--

```js
    // 하나씩 내보내기
    export let name1, name2, …, nameN; // var, const도 동일
    export let name1 = …, name2 = …, …, nameN; // var, const도 동일
    export function functionName(){...}
    export class ClassName {...}

    // 목록으로 내보내기
    export { name1, name2, …, nameN };

    // 내보내면서 이름 바꾸기
    export { variable1 as name1, variable2 as name2, …, nameN };

    // 비구조화로 내보내기
    export const { name1, name2: bar } = o;

    // 기본 내보내기
    export default expression;
    export default function (…) { … } // also class, function\*
    export default function name1(…) { … } // also class, function\*
    export { name1 as default, … };

    // 모듈 조합
    export \* from …; // does not set the default export
    export \* as name1 from …;
    export { name1, name2, …, nameN } from …;
    export { import1 as name1, import2 as name2, …, nameN } from …;
    export { default } from …;
```

`nameN`

내보낼 식별자 이름. `import`를 사용해 다른 스크립트에서 가져갈 수 있습니다.

설명
--

내보내기에는 두 종류, **유명**(named)과 **기본**(default) 내보내기가 있습니다. 모듈 하나에서, 유명 내보내기는 여러 개 존재할 수 있지만 기본 내보내기는 하나만 가능합니다. 각 종류는 위의 구문 중 하나와 대응합니다.

* 유명 내보내기

```js
// 먼저 선언한 식별자 내보내기
export { myFunction, myVariable };

// 각각의 식별자 내보내기
// (변수, 상수, 함수, 클래스)
export let myVariable = Math.sqrt(2);
export function myFunction() { ... };
```

* 기본 내보내기

```js
// 먼저 선언한 식별자 내보내기
export { myFunction as default };

// 각각의 식별자 내보내기
export default function () { ... };
export default class { ... }
```

유명 내보내기는 여러 값을 내보낼 때 유용합니다. 가져갈 때는 내보낸 이름과 동일한 이름을 사용해야 합니다.

반면 기본 내보내기는 어떤 이름으로도 가져올 수 있습니다.

```js
// test.js
let k;
export default k = 12;
```

```js
// 임의의 다른 파일
import m from "./test"; // k가 기본 내보내기이므로, 가져오는 이름으로 k 대신 m을 사용해도 문제 없음
console.log(m); // 12 기록
```

식별자 충돌을 피하기 위해 유명 내보내기 중 이름을 바꿔줄 수도 있습니다.

```js
export { myFunction as function1, myVariable as variable };
```

### 다시 내보내기 / 조합

부모 모듈이 자식 모듈을 가져와서 다시 내보낼 수도 있습니다. 즉, 여러 개의 모듈을 모아놓을 하나의 모듈을 만들 수 있습니다.

```js
export foo from "bar.js";
```

위 구문은 아래와 동일합니다.

```js
import foo from 'bar.js';
export foo;
```

예제
--

### 유명 내보내기 사용

어떤 모듈에서 다음과 같은 코드를 가진다고 해보겠습니다.

```js
// module "my-module.js"
function cube(x) {
  return x \* x \* x;
}
const foo = Math.PI + Math.SQRT2;
var graph = {
  options: {
    color: "white",
    thickness: "2px",
  },
  draw: function () {
    console.log("From graph draw function");
  },
};
export { cube, foo, graph };
```

다른 스크립트에서는 아래와 같이 사용할 수 있습니다.

```js
// You should use this script in html with the type module.
// For example:
// <script type="module" src="./demo.js"></script>
//
// Open the page in a http server, otherwise there will be a CORS policy error.
//
// script demo.js

import { cube, foo, graph } from "my-module";
graph.options = {
  color: "blue",
  thickness: "3px",
};
graph.draw();
console.log(cube(3)); // 27
console.log(foo); // 4.555806215962888
```

### 기본 내보내기 사용

단일 값을 내보낼 때나 모듈의 폴백 값이 필요할 땐 기본 내보내기를 사용할 수 있습니다.

```js
// module "my-module.js"
export default function cube(x) {
  return x \* x \* x;
}
```

그런 다음, 다른 스크립트에서 가져오는건 간단합니다:

```js
import cube from "./my-module.js";
console.log(cube(3)); // 27
```

`export default`를 사용할 때 `var`, `let`, `const`는 사용하지 못합니다.

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-exports |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `import`
* JavaScript 모듈 안내서
* ES6 in Depth: Modules, Hacks blog post by Jason Orendorff
* ES modules: A cartoon deep-dive, Hacks blog post by Lin Clark
* Axel Rauschmayer's book: "Exploring JS: Modules"


const - JavaScript

const
=====

**`const` 선언**은 블록 범위의 상수를 선언합니다. 상수의 값은 재할당할 수 없으며 다시 선언할 수도 없습니다.

시도해보기
-----

구문
--

```js
    const name1 = value1 [, name2 = value2 [, ... [, nameN = valueN]]];
```

`nameN`

상수의 이름. 아무 유효한 식별자를 사용할 수 있습니다.

`valueN`

상수의 값. 아무 유효한 표현식이나 가능합니다.

설명
--

이 선언은 선언된 함수에 전역 또는 지역일 수 있는 상수를 만듭니다. 상수 초기자(initializer)가 필요합니다. 즉 선언되는 같은 문에 그 값을 지정해야 합니다(이는 나중에 변경될 수 없는 점을 감안하면 말이 됩니다).

상수는 `let` 문을 사용하여 정의된 변수와 마찬가지로 블록 범위(block-scope)입니다. 상수의 값은 재할당을 통해 바뀔 수 없고 재선언될 수 없습니다.

`let`에 적용한 "일시적 사각 지대"에 관한 모든 고려는, `const`에도 적용합니다.

상수는 같은 범위의 상수 또는 변수와 그 이름을 공유할 수 없습니다.

예제
--

다음 예제는 상수가 어떻게 동작하는지 보입니다. 브라우저 콘솔에서 따라해보세요.

```js
// 주의: 상수 선언에는 대소문자 모두 사용할 수 있지만,
// 일반적인 관습은 모두 대문자를 사용하는 것입니다.

// MY\_FAV를 상수로 정의하고 그 값을 7로 함
const MY\_FAV = 7;

// 에러가 발생함
MY\_FAV = 20;

// 7 출력
console.log("my favorite number is: " + MY\_FAV);

// 상수를 재선언하려는 시도는 오류 발생 - Uncaught SyntaxError: Identifier 'MY\_FAV' has already been declared
const MY\_FAV = 20;

// MY\_FAV라는 이름은 위에서 상수로 예약되어 있어서 역시 실패함.
var MY\_FAV = 20;

// 역시 오류가 발생함
let MY\_FAV = 20;

// 블록 범위의 특성을 아는게 중요
if (MY\_FAV === 7) {
    // 블록 범위로 지정된 MY\_FAV 라는 변수를 만드므로 괜찮습니다
    // (let으로 const 변수가 아닌 블록 범위를 선언하는 것과 똑같이 동작합니다)
    let MY\_FAV = 20;

    // MY\_FAV는 이제 20입니다
    console.log('my favorite number is ' + MY\_FAV);

    // 이 선언은 전역으로 호이스트되고 에러가 발생합니다.
    var MY\_FAV = 20;
}

// MY\_FAV는 여전히 7
console.log('my favorite number is ' + MY\_FAV);

// const 선언시에 초기값을 생략해서 오류 발생
const FOO;

// const는 오브젝트에도 잘 동작합니다
const MY\_OBJECT = {'key': 'value'};

// 오브젝트를 덮어쓰면 오류가 발생합니다
MY\_OBJECT = {'OTHER\_KEY': 'value'};

// 하지만 오브젝트의 키는 보호되지 않습니다.
// 그러므로 아래 문장은 문제없이 실행됩니다
MY\_OBJECT.key = 'otherValue'; // 오브젝트를 변경할 수 없게 하려면 Object.freeze() 를 사용해야 합니다

// 배열에도 똑같이 적용됩니다
const MY\_ARRAY = [];
// 배열에 아이템을 삽입하는 건 가능합니다
MY\_ARRAY.push('A'); // ["A"]
// 하지만 변수에 새로운 배열을 배정하면 에러가 발생합니다
MY\_ARRAY = ['B']
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-let-and-const-declarations |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `var`
* `let`
* JavaScript 안내서의 상수


for - JavaScript

for
===

**`for` 문**은 괄호로 감싸고 세미콜론으로 구분한 세 개의 선택식과, 반복을 수행할 문(주로 블럭문)으로 이루어져 있습니다.

시도해보기
-----

구문
--

```js
for ([initialization]; [condition]; [final-expression])
   statement
```

`initialization`

식(할당식 포함) 또는 변수 선언. 주로 카운터 변수를 초기화할 때 사용합니다. `var` 또는 `let` 키워드를 사용해 새로운 변수를 선언할 수도 있습니다. `var` 키워드로 선언한 변수는 반복문에 제한되지 않습니다. 즉 `for` 문과 같은 범위에 위치합니다. `let` 키워드로 선언한 변수는 반복문의 지역 변수가 됩니다.

식의 결과는 버려집니다.

`condition`

매 반복마다 평가할 식. 평가 결과가 참이라면 `statement`를 실행합니다. 이 식을 넣지 않았을 때 계산 결과는 언제나 참이 됩니다. 계산 결과가 거짓이라면 `for` 문의 바로 다음 식으로 건너 뜁니다.

`final-expression`

매 반복 후 평가할 식. 다음번 `condition` 평가 이전에 발생합니다. 주로 카운터 변수를 증감하거나 바꿀 때 사용합니다.

`statement`

조건의 평가 결과가 참일 때 실행하는 문. 여러 문을 반복 실행하려면 블럭문(`{ ... }`)으로 묶어야 합니다. 아무것도 실행하지 않으려면 공백문 (`;`)을 사용하세요.

예제
--

### `for` 사용하기

다음 `for` 문은 변수 `i`를 선언하고 0으로 초기화하여 시작합니다. `i`가 9보다 작은지를 확인하고 맞으면 명령문을 수행한 후 `i`의 값을 1 높입니다.

```js
for (var i = 0; i < 9; i++) {
  console.log(i);
  // 기타 등등
}
```

### 선택적 식 사용

`for` 반복문의 3개 식은 모두 선택 사항입니다.

예를 들어, 변수를 초기화하려고 `initialization` 블럭을 사용할 필요는 없습니다.

```js
var i = 0;
for (; i < 9; i++) {
  console.log(i);
  // 기타 등등
}
```

`initialization` 블럭처럼 `condition` 블럭도 선택 사항입니다. 다만 이 경우, 반복문 본문에 무한 반복을 탈출할 수 있는 장치를 추가해야 합니다.

```js
for (var i = 0; ; i++) {
  console.log(i);
  if (i > 3) break;
  // 기타 등등
}
```

세 가지 모두 생략할 수도 있습니다. 위와 같이 `break` 문을 사용해 반복을 탈출할 수 있도록 추가하고, 변수를 수정해 탈출 조건이 언젠가 참이 되도록 해야 합니다.

```js
var i = 0;

for (;;) {
  if (i > 3) break;
  console.log(i);
  i++;
}
```

### 문 없이 `for` 사용하기

다음 `for` 반복 사이클은 노드의 위치 오프셋을 `final-expression`에서 계산해 문이나 블럭문이 필요하지 않으므로 세미콜론을 사용합니다.

```js
function showOffsetPos(sId) {
  var nLeft = 0,
    nTop = 0;

  for (
    var oItNode = document.getElementById(sId) /\* initialization \*/;
    oItNode /\* condition \*/;
    nLeft += oItNode.offsetLeft,
      nTop += oItNode.offsetTop,
      oItNode = oItNode.offsetParent /\* final-expression \*/
  ); /\* semicolon \*/

  console.log(
    "Offset position of '" +
      sId +
      "' element:\n left: " +
      nLeft +
      "px;\n top: " +
      nTop +
      "px;",
  );
}

/\* Example call: \*/

showOffsetPos("content");

// Output:
// "Offset position of "content" element:
// left: 0px;
// top: 153px;"
```

**참고:** 여기서 쓰인 세미콜론은, JavaScript가 **필수로 요구하는 몇 안되는 세미콜론**입니다. 물론 세미콜론 없이는 반복 사이클 선언의 바로 다음 줄을 반복 본문으로 인식합니다.

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-for-statement |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

참조
--

* 공백문
* `break`
* `continue`
* `while`
* `do...while`
* `for...in`
* `for...of`


function* - JavaScript

function\*
==========

**`function*`** 선언 (끝에 별표가 있는 `function` keyword) 은 *generator function* 을 정의하는데, 이 함수는 `Generator` 객체를 반환합니다.

시도해보기
-----

generator function 은 `GeneratorFunction` 생성자와 `function* expression` 을 사용해서 정의할 수 있습니다.

문법
--

```js
    function\* name([param[, param[, ... param]]]) {
       statements
    }
```

`name`

함수명.

`param`

함수에 전달되는 인수의 이름. 함수는 인수를 255개까지 가질 수 있다.

`statements`

함수의 본체를 구성하는 구문들.

설명
--

Generator는 빠져나갔다가 나중에 다시 돌아올 수 있는 함수입니다. 이때 컨텍스트(변수 값)는 출입 과정에서 저장된 상태로 남아 있습니다.

Generator 함수는 호출되어도 즉시 실행되지 않고, 대신 함수를 위한 Iterator 객체가 반환됩니다. Iterator의 `next()` 메서드를 호출하면 Generator 함수가 실행되어 **`yield`** 문을 만날 때까지 진행하고, 해당 표현식이 명시하는 Iterator로부터의 반환값을 반환합니다. **`yield*`** 표현식을 마주칠 경우, 다른 Generator 함수가 위임(delegate)되어 진행됩니다.

이후 `next()` 메서드가 호출되면 진행이 멈췄던 위치에서부터 재실행합니다. `next()` 가 반환하는 객체는 `yield`문이 반환할 값(yielded value)을 나타내는 `value` 속성과, Generator 함수 안의 모든 `yield` 문의 실행 여부를 표시하는 boolean 타입의 `done` 속성을 갖습니다. `next()` 를 인자값과 함께 호출할 경우, 진행을 멈췄던 위치의 `yield` 문을 `next()` 메서드에서 받은 인자값으로 치환하고 그 위치에서 다시 실행하게 됩니다.

예시
--

### 간단한 예제

```js
function\* idMaker() {
  var index = 0;
  while (index < 3) yield index++;
}

var gen = idMaker();

console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // undefined
// ...
```

### yield\* 를 사용한 예제

```js
function\* anotherGenerator(i) {
  yield i + 1;
  yield i + 2;
  yield i + 3;
}

function\* generator(i) {
  yield i;
  yield\* anotherGenerator(i);
  yield i + 10;
}

var gen = generator(10);

console.log(gen.next().value); // 10
console.log(gen.next().value); // 11
console.log(gen.next().value); // 12
console.log(gen.next().value); // 13
console.log(gen.next().value); // 20
```

### Generator 에 인자값을 넘기는 예제

```js
function\* logGenerator() {
  console.log(yield);
  console.log(yield);
  console.log(yield);
}

var gen = logGenerator();

// the first call of next executes from the start of the function
// until the first yield statement
gen.next();
gen.next("pretzel"); // pretzel
gen.next("california"); // california
gen.next("mayonnaise"); // mayonnaise
```

### Generator 는 생성자로서 사용될 수 없다

```js
function\* f() {}
var obj = new f(); // throws "TypeError: f is not a constructor"
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-generator-function-definitions |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

관련 항목
-----

* `function* expression`
* `GeneratorFunction` object
* The Iterator protocol (en-US)
* `yield`
* `yield*`
* `Function` object
* `function declaration`
* `function expression`
* `Functions and function scope` (en-US)
* Other web resources:
    + Regenerator an ES2015 generator compiler to ES5
    + Forbes Lindesay: Promises and Generators: control flow utopia — JSConf EU 2013
    + Hemanth.HM: The New gen of \*gen(){}
    + Task.js


class - JavaScript

class
=====

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since March 2017.

* Learn more
* See full compatibility
* Report feedback
**`class` 선언**은 프로토타입 기반 상속을 사용하여, 주어진 이름의 새로운 클래스를 만듭니다.

시도해보기
-----

클래스 표현을 사용하여 클래스를 정의할 수도 있습니다. 표현식과 달리 선언문으로는 같은 클래스를 다시 선언하면 오류가 발생합니다.

구문
--

```js
    class name [extends] {
      // class body
    }
```

설명
--

클래스 본문은 엄격 모드에서 실행됩니다. 생성자 속성은 선택 사항입니다..

클래스 선언은 함수 선언과 달리 호이스팅의 대상이 아닙니다.

예제
--

### 간단한 클래스 선언

다음 예제는 우선 `Polygon` 클래스를 정의하고, `Square`라는 이름의 새로운 클래스가 `Polygon`을 상속합니다. 생성자 내부의 `super()`는 생성자 내에서만, 그리고 `this` 키워드를 사용하기 전에만 쓸 수 있다는 점을 주의하세요.

```js
class Polygon {
  constructor(height, width) {
    this.name = "Polygon";
    this.height = height;
    this.width = width;
  }
}

class Square extends Polygon {
  constructor(length) {
    super(length, length);
    this.name = "Square";
  }
}
```

>
> **Warning:** 같은 클래스를 두 번 선언하려고 시도할 때 클래스 선언문으로 같은 클래스를 두 번 선언하면 오류가 발생합니다.
>
>
>

```js
class Foo {}
class Foo {} // Uncaught SyntaxError: Identifier 'Foo' has already been declared
```

이전에 표현식으로 정의한 경우에도 오류가 발생합니다.

```js
var Foo = class {};
class Foo {} // Uncaught TypeError: Identifier 'Foo' has already been declared
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-class-definitions |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

참조
--

* `function` 선언문
* `class` 표현식
* 클래스


label - JavaScript

label
=====

**레이블 구문**은 `break`나 `continue` 구문과 함께 사용할 수 있다. 원하는 식별자로 구문 앞에 레이블을 추가할 수 있다.

>
> **Note:** 레이블을 붙인 반복문이나 블록가 자주 사용되는 것은 아니다. 반복문으로 점프하는 대신에 함수를 호출할 수도 있다.
>
>
>

문법
--

```js
label:
  statement;
```

`label`

JavaScript에서 사용할 수 있는 식별자면 모두 가능하다.

`statement`

구문. break는 모든 레이블 구문에서 사용될 수 있으며, continue는 반복 레이블 구문에서만 사용할 수 있다.

설명
--

반복문에 레이블을 붙이고, break나 continue 구문을 사용해 반복문의 어느 위치에서 작업을 멈추고 어느 위치에서 다시 수행할지를 알려줄 수 있다.

JavaScript에는 goto 구문이 없다는 것에 주의. break나 continue에서만 레이블을 사용할 수 있다.

strict mode 코드에서 "let"을 레이블 이름으로 사용할 수 없다. `SyntaxError`를 발생시킨다. (let은 허용되지 않는 식별자이다.)

예제
--

### for문에서 레이블 continue 사용하기

```js
var i, j;

loop1: for (i = 0; i < 3; i++) {
  //첫번째 for문은 "loop1" 레이블을 붙였다.
  loop2: for (j = 0; j < 3; j++) {
    //두번째 for문은 "loop2" 레이블을 붙였다.
    if (i === 1 && j === 1) {
      continue loop1;
    }
    console.log("i = " + i + ", j = " + j);
  }
}

// 출력 결과:
// "i = 0, j = 0"
// "i = 0, j = 1"
// "i = 0, j = 2"
// "i = 1, j = 0"
// "i = 2, j = 0"
// "i = 2, j = 1"
// "i = 2, j = 2"
// 다음 두 경우를 어떻게 스킵하는지 주목 : "i = 1, j = 1", "i = 1, j = 2"
```

### 레이블 continue문 사용하기

items, tests 배열을 보면 이 예제는 tests를 통과하는 items의 수를 세고 있다.

```js
var itemsPassed = 0;
var i, j;

top: for (i = 0; i < items.length; i++) {
  for (j = 0; j < tests.length; j++) {
    if (!tests[j].pass(items[i])) {
      continue top;
    }
  }

  itemsPassed++;
}
```

### for문에 레이블 break문 사용하기

```js
var i, j;

loop1: for (i = 0; i < 3; i++) {
  //The first for statement is labeled "loop1"
  loop2: for (j = 0; j < 3; j++) {
    //The second for statement is labeled "loop2"
    if (i === 1 && j === 1) {
      break loop1;
    }
    console.log("i = " + i + ", j = " + j);
  }
}

// Output is:
// "i = 0, j = 0"
// "i = 0, j = 1"
// "i = 0, j = 2"
// "i = 1, j = 0"
// Notice the difference with the previous continue example
```

### 레이블 break문 사용하기

items, tests 배열을 보면, 다음 예제는 items가 tests를 모두 통과하는지 판단한다.

```js
var allPass = true;
var i, j;

top: for (i = 0; items.length; i++)
  for (j = 0; j < tests.length; i++)
    if (!tests[j].pass(items[i])) {
      allPass = false;
      break top;
    }
```

### 레이블 붙인 블록에 break 사용하기

간단한 블록에도 레이블을 사용할 수 있지만, 반복문 아닌 레이블에는 break문만 사용할 수 있다.

```js
foo: {
  console.log("face");
  break foo;
  console.log("this will not be executed");
}
console.log("swap");

// 로그는 이렇게 출력된다:

// "face"
// "swap
```

### 레이블 붙인 함수 선언문

ECMAScript 2015에서, 레이블 붙인 함수 선언문은 web compatibility annex of the specification의 non-strict 모드에서 표준화되어 있다.

```js
L: function F() {}
```

strict mode 에서는 `SyntaxError`를 발생시킨다.

```js
"use strict";
L: function F() {}
// SyntaxError: functions cannot be labelled
```

Generator functions는 strict code도 non-strict code에서도 레이블 붙일 수 없다.

```js
L: function\* F() {}
// SyntaxError: generator functions cannot be labelled
```

명세
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-labelled-statements |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

더 알아보기
------

* `break`
* `continue`


break - JavaScript

break
=====

**`break` 문**은 현재 반복문, `switch` (en-US) 문, 또는 `label` 문을 종료하고, 그 다음 문으로 프로그램 제어를 넘깁니다.

시도해보기
-----

구문
--

```js
    break [label];
```

`label` Optional

문의 라벨에 연결한 식별자. 반복문이나 `switch` (en-US)에서 사용하는게 아니면 필수로 제공해야 합니다.

설명
--

`break` 문은 프로그램이 label 달린 문에서 빠져나오게 하는 선택사항 label을 포함합니다. `break` 문은 참조되는 label 내에 중첩되어야 합니다. label 달린 문은 어떤 `block` 문이든 될 수 있습니다. 꼭, loop 문을 달 필요가 없습니다.

예제
--

다음 함수는 `i`가 3일 때 `while` loop를 종료하는 break 문이 있고, 그러고는 3 \* `x`값을 반환합니다.

```js
function testBreak(x) {
  var i = 0;

  while (i < 6) {
    if (i == 3) {
      break;
    }
    i += 1;
  }

  return i \* x;
}
```

다음 코드는 label 달린 블록이 있는 `break` 문을 사용합니다. `break` 문은 자신이 참조하는 label 내에 중첩되어야 합니다. `inner_block`은 `outer_block`내에 중첩되어야 함을 주의하세요.

```js
outer\_block: {
  inner\_block: {
    console.log("1");
    break outer_block; // inner\_block과 outer\_block 둘다 빠져나옴
    console.log(":-("); // 건너뜀
  }
  console.log("2"); // 건너뜀
}
```

다음 코드는 또한 label 달린 블록이 있는 break 문을 사용하지만 그 `break` 문이 `block_2`를 참조하지만 `block_1` 내에 있기에 구문 오류(Syntax Error)가 발생합니다. `break` 문은 항상 자신이 참조하는 label 내에 중첩되어야 합니다.

```js
block\_1: {
  console.log('1');
  break block_2; // SyntaxError: label을 찾을 수 없음
}

block\_2: {
  console.log('2');
}
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-break-statement |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `continue`
* `label`
* `switch` (en-US)


if...else - JavaScript

if...else
=========

**`if` 문**은 지정한 조건이 참인 경우 명령문(statement)을 실행합니다. 조건이 거짓인 경우 또 다른 명령문이 실행 될 수 있습니다.

시도해보기
-----

구문
--

```js
    if (condition)
       statement1
    [else
       statement2]
```

`condition`

참 또는 거짓으로 평가되는 표현식입니다.

`statement1`

 조건이 참으로 평가될 경우 실행되는 문입니다.
 중첩된 if구문을 포함하여 어떤 구문이든 쓸 수 있습니다. 다중구문을 사용할 경우 ({ ... })블럭 구문 으로 그룹화 하고 실행하지 않으려면 빈 구문을 사용합니다.

`statement2`

이 구문은 조건이 거짓일경우 다른 조항이 있을 때 실행되는 구문입니다. 블록 문과 if문의 중첩을 호함한 모든문이 될 수 있습니다.

설명
--

 다중의 if...else 문은 else if 절을 만들기 위해 중첩될 수 있다.
 JavaScript에서는 elseif (하나의 단어) 키워드가 존재하지 않는다.

```js
    if (조건1)
       명령문1
    else if (조건2)
       명령문2
    else if (조건3)
       명령문3
    ...
    else
       명령문N
```

아래 작업한 것을 보면, if문을 중첩 사용하면 들여쓰기된 것이 제대로 보여집니다.

```js
    if (조건1)
       명령문1
    else
       if (조건2)
          명령문2
       else
          if (조건3)
    ...
```

 하나의 절에서 여러개의 명령문들을 실행하려면, 그 명령문들을 그룹화하는 블록 명령문 ({ ... }) 블럭구문을 사용한다.
 일반적으로, 블럭구문을 항상 사용하는 것은 좋은 연습입니다. 특히 중첩된 if 문과 관련되어
 있는 코드안에서 사용하면 더욱 좋습니다.

```js
if (조건) {
  명령문들1;
} else {
  명령문들2;
}
```

원시 불리언 값인 true (참) 과 false (거짓) 을 불리언 객체의 truthiness (참으로 보이는 것) 과 falsiness (거짓으로 보이는 것)으로 혼동하면 안된다. false, undefined, null, 0, NaN, 또는 빈 스트링 ("") 이 아닌 모든 값, 그리고 false 값인 불리언 객체를 포함하는 모든 객체는 조건으로 사용될 때 truthy 로 간주된다. 예:

```js
var b = new Boolean(false);
if (b) // 이 조건은 참으로 보이는 것 (truthy) 이다.
```

예시
--

### `if...else` 사용하기

```js
if (cipher_char === from_char) {
  result = result + to_char;
  x++;
} else {
  result = result + clear_char;
}
```

### `else if` 사용하기

JavaScript에는 elseif 구문이 없다. 그러나, else if 를 사용할 수 있다.

```js
if (x > 5) {
} else if (x > 50) {
} else {
}
```

### 조건식의 값을 지정하기

 조건식을 단순하게 지정하는 것은 좋지 않습니다.
 왜냐하면, 코드를 흘깃 보면 값을 지정한것을 평등한것으로 혼동할 수 있기 때문입니다. 예를들어, 다음코드를 사용하지 마세요:

```js
if (x = y) {
  /\* do the right thing \*/
}
```

당신이 조건식에 값의 지정을 해야할 경우, 일반적인 관행은 그 할당된 것 주위에 추가 괄호를 넣어야 합니다. 예를들면:

```js
if ((x = y)) {
  /\* do the right thing \*/
}
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-if-statement |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `block`
* `switch` (en-US)
* 삼항 조건 연산자


while - JavaScript

while
=====

**`while` 문**은 조건문이 참일 때 실행되는 반복문이다. 조건은 문장안이 실행되기 전에 참, 거짓을 판단한다.

문법
--

```js
while (condition) {
  statement
}
```

`조건`

반복이 시작되기 전에 조건문은 참,거짓을 판단받게 된다. 만약 조건문이 참이라면, while문 안의 문장들이 실행된다. 거짓이라면, 문장은 그냥 while 반복문 후로 넘어간다.

`문장`

조건문이 참일 때만 while문 속의 문장들이 실행된다. 반복문 속에 여러개의 문장을 사용하고 싶다면 중괄호 { } 를 통해 문장들을 하나로 묶어야 한다.

예제
--

다음의 while문은 n이 3보다 작을 때까지 반복한다.

```js
var n = 0;
var x = 0;

while (n < 3) {
  n++;
  x += n;
}
```

반복을 살펴보면, n을 x에 계속 더하게 된다. 그러므로 x와 n 변수는 다음의 값을 갖는다.

* 첫번째 반복; n=1 과 x=1
* 두번째 반복; n=2 과 x=3
* 세번째 반복; n=3 과 x=6

세번째 반복후, n<3 이라는 초건은 더 이상 참이아니가 되므로 반복은 종료된다

명세
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-while-statement |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `do...while`
* `for`


continue - JavaScript

continue
========

**`continue`** 문은 현재 또는 레이블이 지정된 루프의 현재 반복에서 명령문의 실행을 종료하고 반복문의 처음으로 돌아가여 루프문의 다음 코드를 실행합니다.

시도해보기
-----

구문
--

```js
    continue [label];
```

`label`

명령문의 레이블과 연관된 식별자.

설명
--

`break` 문과 달리 `continue`는 루프의 실행을 완전히 종료하지 않고 `for`, `while`문에서 다음과 같이 동작합니다.

* `while` 루프에서는 다시 조건으로 점프합니다.
* `for` 루프에서는 업데이트 표현식으로 점프합니다.

`continue` 문에는 현재 루프 대신 레이블이 지정된 루프 문의 다음 반복으로 건너 뛰도록하는 선택적 레이블이 포함될 수 있습니다. 이 경우, `continue` 문은 이 레이블 된 명령문 내에 중첩되어야합니다.

예제
--

### Using `continue` with `while`

다음 예제에서는 `i`의 값이 3일 때 실행되는 `continue`문을 포함하는 `while`을 보여줍니다. 따라서 n은 1, 3, 7 및 12 값을 갖습니다.

```js
var i = 0;
var n = 0;

while (i < 5) {
  i++;

  if (i === 3) {
    continue;
  }

  n += i;
}
```

### label과 함께 `continue` 사용하기

다음 예제에서 `checkiandj`라는 문에는 `checkj`라는 문이 있습니다. `continue`가 발생하면 프로그램은 `checkj` 문의 맨 위에서 계속됩니다. `continue`가 발생할 때마다 `checkj`는 조건이 false를 반환 할 때까지 반복합니다. false가 리턴되면 나머지 `checkiandj` 문이 완료됩니다.

`continue`에 `checkiandj` 레이블이 있으면이 프로그램은 `checkiandj` 문 맨 위에서 계속됩니다.

See also `label`.

```js
var i = 0;
var j = 8;

checkiandj: while (i < 4) {
  console.log("i: " + i);
  i += 1;

  checkj: while (j > 4) {
    console.log("j: " + j);
    j -= 1;

    if (j % 2 == 0) continue checkj;
    console.log(j + " is odd.");
  }
  console.log("i = " + i);
  console.log("j = " + j);
}
```

출력:

```js
i: 0

// start checkj
j: 8
7 is odd.
j: 7
j: 6
5 is odd.
j: 5
// end checkj

i = 1
j = 4

i: 1
i = 2
j = 4

i: 2
i = 3
j = 4

i: 3
i = 4
j = 4
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-continue-statement |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

함께 보기
-----

* `break`
* `label`


for...of - JavaScript

for...of
========

**`for...of` 명령문**은 반복가능한 객체 (`Array`, `Map`, `Set` (en-US), `String`, `TypedArray`, arguments 객체 등을 포함)에 대해서 반복하고 각 개별 속성값에 대해 실행되는 문이 있는 사용자 정의 반복 후크를 호출하는 루프를 생성합니다.

시도해보기
-----

구문
--

```js
for (variable of iterable) {
  statement;
}
```

`variable`

각 반복에 서로 다른 속성값이 *variable*에 할당됩니다.

`iterable`

반복되는 열거가능(enumerable)한 속성이 있는 객체.

예제
--

### `Array`에 대해 반복

```js
let iterable = [10, 20, 30];

for (let value of iterable) {
  console.log(value);
}
// 10
// 20
// 30
```

`let` 대신 `const`도 사용할 수 있습니다, 블록 내부 변수를 수정하지 않는 경우.

```js
let iterable = [10, 20, 30];

for (const value of iterable) {
  console.log(value);
}
// 10
// 20
// 30
```

### `String`에 대해 반복

```js
let iterable = "boo";

for (let value of iterable) {
  console.log(value);
}
// "b"
// "o"
// "o"
```

### `TypedArray`에 대해 반복

```js
let iterable = new Uint8Array([0x00, 0xff]);

for (let value of iterable) {
  console.log(value);
}
// 0
// 255
```

### `Map`에 대해 반복

```js
let iterable = new Map([
  ["a", 1],
  ["b", 2],
  ["c", 3],
]);

for (let entry of iterable) {
  console.log(entry);
}
// [a, 1]
// [b, 2]
// [c, 3]

for (let [key, value] of iterable) {
  console.log(value);
}
// 1
// 2
// 3
```

### `Set` (en-US)에 대해 반복

```js
let iterable = new Set([1, 1, 2, 2, 3, 3]);

for (let value of iterable) {
  console.log(value);
}
// 1
// 2
// 3
```

### DOM 컬렉션에 대해 반복

`NodeList` 같은 DOM 컬렉션에 대해 반복: 다음 예는 article의 직계 자손인 paragraph에 `read` 클래스를 추가합니다:

```js
// 주의: 이는 NodeList.prototype[Symbol.iterator]가
// 구현된 플랫폼에서만 작동합니다
let articleParagraphs = document.querySelectorAll("article > p");

for (let paragraph of articleParagraphs) {
  paragraph.classList.add("read");
}
```

### 생성기에 대해 반복

생성기에 대해서도 반복할 수 있습니다:

```js
function\* fibonacci() {
  // 생성기 함수
  let [prev, curr] = [1, 1];
  while (true) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

for (let n of fibonacci()) {
  console.log(n);
  // 1000에서 수열을 자름
  if (n >= 1000) {
    break;
  }
}
```

### 다른 반복가능 객체에 대해 반복

iterable 프로토콜을 명시해서 구현하는 객체에 대해서도 반복할 수 있습니다:

```js
var iterable = {
  [Symbol.iterator]() {
    return {
      i: 0,
      next() {
        if (this.i < 3) {
          return { value: this.i++, done: false };
        }
        return { value: undefined, done: true };
      },
    };
  },
};

for (var value of iterable) {
  console.log(value);
}
// 0
// 1
// 2
```

### `for...of`와 `for...in`의 차이

`for...in` 루프는 객체의 모든 열거가능한 속성에 대해 반복합니다.

`for...of` 구문은 **컬렉션** 전용입니다. 모든 객체보다는, `[Symbol.iterator]` 속성이 있는 모든 컬렉션 요소에 대해 이 방식으로 반복합니다.

다음 예는 `for...of` 루프와 `for...in` 루프의 차이를 보입니다.

```js
Object.prototype.objCustom = function () {};
Array.prototype.arrCustom = function () {};

let iterable = [3, 5, 7];
iterable.foo = "hello";

for (let i in iterable) {
  console.log(i); // logs 0, 1, 2, "foo", "arrCustom", "objCustom"
}

for (let i of iterable) {
  console.log(i); // logs 3, 5, 7
}
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-for-in-and-for-of-statements |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* for each...in - 비슷한 문이지만, 속성 이름 자체보다는 객체의 속성값을 반복합니다 (사라짐).
* `Array.prototype.forEach()`
* Map.prototype.forEach()


block - JavaScript

block
=====

**블록문**(또는 다른 언어에서는 복합문)은 0개 이상의 구문을 묶을 때 사용합니다.
 블록은 한 쌍의 중괄호로 구성하며 선택적으로 레이블을 붙일 수 있습니다.

시도해보기
-----

문법
--

### 블록문

```js
{
  StatementList;
}
```

### 레이블된 블록문

```js
LabelIdentifier: {
  StatementList;
}
```

`StatementList`

블록문 내의 구문.

`LabelIdentifier`

시각적인 구분, 또는 `break`문의 대상으로 쓸 label.

설명
--

 다른 언어에서 블록문은 **복합문**이라고 부르기도 합니다. 블록문을 쓰면 JavaScript가 하나의 문을 기대하는 곳에서 다수의 문을 실행할 수
 있습니다. JavaScript에서 이렇게 문을 묶는건 흔히 쓰이는 기법입니다. 반대 개념으로는 공백문이 있으며, 이는 하나의 구문을 기대하는 곳에 아무것도 제공하지 않는 것입니다.

블록문은 흔히 `if...else`과 `for`문 관련해서 사용됩니다.

예제
--

### 엄격하지 않은 모드에서 변수 또는 함수 선언의 블록 범위 규칙

#### `var` 사용 시

`var`로 선언한 변수는 블록 범위를 **가지지 않습니다**.
 블록 내에서 선언한 변수의 범위는 함수나 스크립트가 되어, 값 할당의 영향이 블록 바깥까지 미칩니다.
 다른 말로는 블록문이 범위를 만들지 않습니다.
 "독립" 블록문도 유효한 구문이긴 하지만, C와 Java의 블록에 기대하는걸 JavaScript에서도 기대하면 안됩니다.
 예를 들어보겠습니다.

 엄격하지 않은 모드에서 `var`로 선언한 변수 혹은 함수 선언에 의해 생성된 변수는 블록 범위를 **가지지 않습니다**.
 블록 내에서 선언한 변수는 이 변수를 포함한 함수나 스크립트까지 범위가 지정되며, 변수의 설정 효과는 블록을 넘어서도 지속됩니다. 즉, 블록문에 범위가 도입되지 않습니다. 예:

```js
var x = 1;
{
  var x = 2;
}
console.log(x); // 콘솔에 2를 출력합니다
```

콘솔 출력 결과는 2입니다. 블록 안의 `var x`과 블록 앞의 `var x` 문과 동일한 범위에 있기 때문입니다.

엄격하지 않은 코드에서는, 블록 내부의 함수 선언이 이상하게 동작합니다. 사용하지 마십시오.

#### 엄격 모드에서 let, const 혹은 함수 선언의 범위 규칙

반면 `let`과 `const`로 선언한 식별자는 블록 범위를 **가집니다**.

```js
let x = 1;
{
  let x = 2;
}
console.log(x); // 1이 콘솔에 찍힙니다.
```

`x = 2`는 선언한 블록으로 범위가 제한됩니다.

`const`도 마찬가지입니다.

```js
const c = 1;
{
  const c = 2;
}
console.log(c); // 1이 콘솔에 찍히며, SyntaxError 예외가 발생하지 않습니다.
```

 블록 내의 `const c = 2`가 `SyntaxError: Identifier 'c' has already been declared`를 던지지 않는 점에 주목하세요. 블록
 범위 안이라 별개의 식별자이기 때문입니다.

 ES2015의 엄격 모드부터, 블록 내의 함수는 해당 블록으로 범위가 제한됩니다. ES2015 이전의
 엄격 모드에서는 블록 레벨 함수를 사용할 수 없었습니다.

명세
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-block |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `while`
* `if...else`
* `let`


메서드 정의 - JavaScript

메서드 정의
======

ECMAScript 2015 를 시작으로, 객체 초기자(initializer)에 메서드 정의를 위한 더 짧은 구문이 도입되었습니다. 이는 메서드 명에 할당된 함수를 위한 단축입니다.

구문
--

```js
    var obj = {
      property( parameters… ) {},
      \*generator( parameters… ) {},
    // 키(속성) 계산값과도 함께:
      [property]( parameters… ) {},
      \*[generator]( parameters… ) {},
    // ES5 getter/setter 구문과 비교해 보세요:
      get property() {},
      set property(value) {}
    };
```

설명
--

단축 구문은 ECMAScript 5에 도입된 getter 및 setter 구문과 비슷합니다.

다음 코드가 주어지면:

```js
var obj = {
  foo: function () {},
  bar: function () {},
};
```

이제 이를 아래로 줄일 수 있습니다:

```js
var obj = {
  foo() {},
  bar() {},
};
```

**주의 :** 단축 구문은 익명(anonymous) 함수 (…`foo: function() {}`… 에서처럼) 대신 유명(named) 함수를 사용합니다. 유명 함수는 함수 본체에서 호출될 수 있습니다 (이는 참조할 식별자가 없기에 익명 함수에게는 불가능합니다). 자세한 사항은, `function` 참조.

### 단축 생성기 메서드

생성기 메서드는 단축 구문을 사용해서도 정의될 수 있습니다. 단축 구문 내 별표(\*)는 생성기 속성명 앞에 와야 함을 주의하세요. 즉, `* g(){}`는 작동하지만 `g *(){}`는 아닙니다.

```js
// 유명 속성 사용 (ES2015 이전)
var obj2 = {
  g: function\* () {
    var index = 0;
    while (true) yield index++;
  },
};

// 단축 구문을 쓰는 같은 객체
var obj2 = {
  \*g() {
    var index = 0;
    while (true) yield index++;
  },
};

var it = obj2.g();
console.log(it.next().value); // 0
console.log(it.next().value); // 1
```

### 메서드 정의는 생성 불가능합니다

모든 메서드 정의는 생성자가 아니고 인스턴스화하려고 하는 경우 `TypeError` 예외가 발생합니다.

```js
var obj = {
  method() {},
};
new obj.method(); // TypeError: obj.method는 생성자가 아닙니다

var obj = {
  \*g() {},
};
new obj.g(); // TypeError: obj.g는 생성자가 아닙니다 (ES2016에서 바뀜)
```

예
-

### 간단한 테스트 사례

```js
var obj = {
  a : "foo",
  b(){ return this.a; }
};
console.log(obj.b()); // "foo"
```

### 속성 계산명

단축 구문은 속성 계산명(computed property name)도 지원합니다.

```js
var bar = {
  foo0: function () {
    return 0;
  },
  foo1() {
    return 1;
  },
  ["foo" + 2]() {
    return 2;
  },
};

console.log(bar.foo0()); // 0
console.log(bar.foo1()); // 1
console.log(bar.foo2()); // 2
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-method-definitions |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

참조
--

* `get`
* `set`
* 어휘 문법 (en-US)


접근자 - JavaScript

접근자
===

**`get`** 구문은 객체의 속성 접근 시 호출할 함수를 바인딩합니다. 이 구문은 classes에서도 사용할 수 있습니다.

시도해보기
-----

구문
--

```js
{ get prop() { /\* … \*/ } }
{ get [expression]() { /\* … \*/ } }
```

몇 가지 추가적인 구문의 제한이 있습니다.

* getter는 매개변수가 정확히 0개여야 합니다.
### 매개변수

`prop`

지정된 함수에 바인딩할 속성의 이름입니다. 객체 초기자의 다른 속성과 동일한 방식으로 문자열 리터럴, 숫자 리터럴 또는 식별자일 수 있습니다.

`expression`

속성 이름에 대한 표현식을 사용하여 지정된 함수에 바인딩할 수도 있습니다.

설명
--

 동적으로 계산된 값을 반환하는 속성에 대한 접근을 허용하는 것이 바람직한 경우도 있습니다.
 명시적인 메서드 호출을 사용하지 않고도 내부 변수의 상태를 반영하고 싶을 수 있습니다.
 JavaScript에서는 접근자(*getter*)를 사용하여 이 작업을 수행할 수 있습니다.

접근자와 설정자를 함께 사용하여 일종의 의사 속성을 생성하는 것은 가능하지만 속성에 바인딩된 접근자와 해당 속성이 실제로 값을 보유하도록 하는 것은 동시에 불가능합니다.

예제
--

### 객체 초기자에서 새로운 객체의 접근자 정의하기

 다음 예제는 객체 `obj`에 의사 속성 `latest`를 생성합니다.
 `latest`는 배열 `log`의 마지막 요소를 반환합니다.

```js
const obj = {
  log: ["example", "test"],
  get latest() {
    if (this.log.length === 0) return undefined;
    return this.log[this.log.length - 1];
  },
};
console.log(obj.latest); // "test"
```

`latest`에 다른 값을 할당하려 해도 아무 변화도 없을 것입니다.

### 클래스에서 접근자 사용

똑같은 구문을 사용해 클래스 인스턴스에서 사용할 수 있는 공용 인스턴스 접근자를 정의할 수 있습니다. 클래스에서는 메서드 사이에 쉼표로 구분할 필요가 없습니다.

```js
class ClassWithGetSet {
  #msg = "hello world";
  get msg() {
    return this.#msg;
  }
  set msg(x) {
    this.#msg = `hello ${x}`;
  }
}

const instance = new ClassWithGetSet();
console.log(instance.msg); // "hello world"

instance.msg = "cake";
console.log(instance.msg); // "hello cake"
```

접근자 속성은 클래스의 `prototype`으로 정의되므로 클래스의 모든 인스턴스에서 공유됩니다. 객체 리터럴의 접근자 속성과 달리 클래스의 접근자 속성은 열거할 수 없습니다.

Static 설정자와 private 설정자는 유사한 구문을 사용하며, `static`과 private class features 페이지에 설명되어 있습니다.

### `delete` 연산자로 접근자 제거하기

접근자를 삭제하려면 간단히 `delete` (en-US) 연산자를 사용하세요.

```js
delete obj.latest;
```

### `defineProperty`를 이용해 이미 존재하는 객체에 접근자 정의하기

이미 존재하는 객체에 접근자를 추가하려면 `Object.defineProperty()`를 사용하세요.

```js
const o = { a: 0 };

Object.defineProperty(o, "b", {
  get() {
    return this.a + 1;
  },
});

console.log(o.b); // 접근자 실행, a + 1 반환 (즉, 1)
```

### 계산된 속성 이름 사용하기

```js
const expr = "foo";

const obj = {
  get [expr]() {
    return "bar";
  },
};

console.log(obj.foo); // "bar"
```

### 정적 접근자 정의하기

```js
class MyConstants {
  static get foo() {
    return "foo";
  }
}

console.log(MyConstants.foo); // 'foo'
MyConstants.foo = "bar";
console.log(MyConstants.foo); // 'foo', 정적 접근자의 값 변경 불가
```

### 똑똑한 / 자기 덮어쓰기 / 느긋한 접근자

 접근자를 사용하면 객체에 속성을 **정의**하되, 접근하기 전에는 속성의 값을 **계산**하지 않을 수 있습니다.
 접근자는 값이 실제로 필요한 상황이 오기 전까지 계산 비용을 미루는 것입니다.
 사용하지 않으면 비용을 지불할 일도 없습니다.

 속성 값의 계산을 느긋하게 만들거나 미루고, 나중에 접근할 수 있도록 캐시에 저장하는
 추가 최적화 기법은 **똑똑한(*smart*) 또는 메모화(메모이제이션) 접근자**라고 합니다.
 똑똑한 접근자 속성의 값은 접근자를 처음 호출할 때 계산하는 동시에 캐시에 저장됩니다.
 덕분에 속성에 추가 접근 시 캐시에서 값을 즉시 반환하므로 값을 다시 계산하는 수고를 피할 수 있습니다.
 똑똑한 접근자는 다음과 같은 상황에 유용합니다.

* 값의 계산 비용이 큰 경우. (RAM이나 CPU 시간을 많이 소모하거나, 워커 스레드를 생성하거나, 원격 파일을 불러오는 등)
* 값이 지금 당장 필요하지 않은 경우. 나중에 사용할 수도 있고, 경우에 따라 아예 사용되지 않을 수 있습니다.
* 값을 사용하면 여러 번 접근하게 되므로 변경되지 않거나 다시 계산할 필요가 없는 값은 다시 계산할 필요가 없습니다.

**참고:** 즉, 값이 변경될 것으로 예상되는 속성에 대해 게으른 접근자를 작성하면 값을 다시 계산하지 않으므로 게으른 접근자를 작성해서는 안 됩니다.

모든 접근자가 처음부터 '느긋'하며 '메모화'되는 것은 아닙니다. 이런 동작이 필요하면 직접 구현해야 합니다.

 다음 예제의 접근자 속성은 어느 객체의 자체 속성으로 존재합니다.
 이 속성에 접근하는 순간, 접근자는 스스로 자신을 객체에서 제거하는 동시에 같은 이름의 속성을 다시 추가하지만, 이때는 접근자가 아니라 데이터 속성으로 추가합니다.
 마지막으로 그 속성의 값을 반환합니다.

```js
const obj = {
  get notifier() {
    delete this.notifier;
    this.notifier = document.getElementById("bookmarked-notification-anchor");
    return this.notifier;
  },
};
```

### get vs. defineProperty

`get` 키워드와 `Object.defineProperty()`는 비슷한 결과를 내지만, `classes`에 사용할 경우 미묘한 차이가 생깁니다.

`get`을 사용할 경우, 해당 속성은 인스턴스의 프로토타입에 정의됩니다.
 그러나 `Object.defineProperty()`를 사용할 경우 속성을 인스턴스 자체에 직접 정의하게 됩니다.

```js
class Example {
  get hello() {
    return "world";
  }
}

const obj = new Example();
console.log(obj.hello);
// "world"

console.log(Object.getOwnPropertyDescriptor(obj, "hello"));
// undefined

console.log(
  Object.getOwnPropertyDescriptor(Object.getPrototypeOf(obj), "hello"),
);
// { configurable: true, enumerable: false, get: function get hello() { return 'world'; }, set: undefined }
```

명세
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-method-definitions |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* 객체로 작업하기
* 함수
* `설정자`
* `Object.defineProperty()`
* 객체 초기자
* `class`
* 속성 접근자
* Jeff Walden (2010)의 Incompatible ES5 change: literal getter and setter functions must now have exactly zero or one arguments
* Jeff Walden (2010)의 More SpiderMonkey changes: ancient, esoteric, very rarely used syntax for creating getters and setters is being removed


arguments 객체 - JavaScript

arguments 객체
============

**`arguments`** 객체는 함수에 전달된 인수에 해당하는 `Array` 형태의 객체입니다.

**참고:** ES6 호환 코드를 작성 중이라면 되도록 나머지 매개변수 구문을 사용해야 합니다.

**참고:** "`Array` 형태"란 `arguments`가 `length` 속성과 더불어 0부터 인덱스 된 다른 속성을 가지고 있지만, `Array`의 `forEach`, `map`과 같은 내장 메서드를 가지고 있지 않다는 뜻입니다.

시도해보기
-----

구문
--
```

    arguments
```

설명
--

`arguments` 객체는 모든 함수 내에서 이용 가능한 지역 변수입니다. `arguments` 객체를 사용하여 함수 내에서 모든 인수를 참조할 수 있으며, 호출할 때 제공한 인수 각각에 대한 항목을 갖고 있습니다. 항목의 인덱스는 0부터 시작합니다.

예를 들어, 함수가 세 개의 인수를 받은 경우 다음과 같이 접근할 수 있습니다.

```js
arguments[0];
arguments[1];
arguments[2];
```

각 인수를 설정하거나 재할당할 수도 있습니다.

```js
arguments[1] = "new value";
```

`arguments` 객체는 `Array`가 아닙니다. `Array`와 비슷하지만, `length` 빼고는 `pop()`과 같은 어떤 `Array` 속성도 없습니다. 그러나 실제 `Array`로 변환할 수 있습니다:

```js
var args = Array.prototype.slice.call(arguments);
var args = [].slice.call(arguments);
```

`arguments`를 실제 `Array`로 변환하기 위해 ES2015의 `Array.from()` 메서드 또는 전개 연산자를 사용할 수도 있습니다.

```js
var args = Array.from(arguments);
var args = [...arguments];
```

당신이 형식상 받기로 선언된 것보다 많은 인수로 함수를 호출하는 경우 `arguments` 객체를 사용할 수 있습니다. 이 기법은 가변 인수가 전달될 수 있는 함수에 유용합니다. 함수에 전달된 인수의 수를 결정하기 위해 `arguments.length` (en-US)를 쓰세요, 그 뒤에 `arguments` 객체를 사용하여 각 인수를 처리하세요. 함수 signature에 매개변수의 수를 결정하기 위해서는, `Function.length` 속성을 쓰세요.

속성
--

`arguments.callee`

현재 실행 중인 함수를 가리킵니다.

`arguments.caller`
지원이 중단되었습니다

현재 실행 중인 함수를 호출한 함수를 가리킵니다.

`arguments.length`

함수에 전달된 인수의 수를 가리킵니다.

`arguments[@@iterator]`

arguments의 각 인덱스 값을 포함하는 새로운 Array Iterator 객체를 반환합니다.

예제
--

### 여러 문자열을 연결하는 함수 정의하기

이 예는 여러 문자열을 연결하는 함수를 정의합니다. 함수의 유일한 형식 인수는 연결할 항목을 구분하는 문자를 지정하는 문자열입니다. 함수는 다음과 같이 정의됩니다:

```js
function myConcat(separator) {
  var args = Array.prototype.slice.call(arguments, 1);
  return args.join(separator);
}
```

이 함수에 인수를 얼마든지 전달할 수 있으며 리스트 내 항목처럼 각 인수를 사용하여 리스트를 만듭니다.

```js
// "red, orange, blue" 반환
myConcat(", ", "red", "orange", "blue");

// "elephant; giraffe; lion; cheetah" 반환
myConcat("; ", "elephant", "giraffe", "lion", "cheetah");

// "sage. basil. oregano. pepper. parsley" 반환
myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");
```

### HTML 리스트를 만드는 함수 정의하기

이 예는 리스트 HTML을 포함하는 문자열을 만드는 함수를 정의합니다. 함수의 유일한 형식 인수는 리스트가 정렬되지 않은(bulluet(글 머리 기호)가 붙는) 경우 "`u`" 또는 정렬된(번호가 매겨진) 경우 "`o`"인 문자열입니다. 함수는 다음과 같이 정의됩니다:

```js
function list(type) {
  var result = "<" + type + "l><li>";
  var args = Array.prototype.slice.call(arguments, 1);
  result += args.join("</li><li>");
  result += "</li></" + type + "l>"; // end list

  return result;
}
```

이 함수에 인수를 얼마든지 전달할 수 있고, 표시된 유형의 리스트에 항목으로 각 인수를 추가합니다. 예를 들면:

```js
var listHTML = list("u", "One", "Two", "Three");

/\* listHTML은:

"<ul><li>One</li><li>Two</li><li>Three</li></ul>"

\*/
```

### 나머지, 기본 및 비구조화된 매개변수

`arguments` 객체는 나머지 매개변수, 기본 매개변수 또는 비구조화된 매개변수와 함께 사용될 수 있습니다.

```js
function foo(...args) {
  return arguments;
}
foo(1, 2, 3); // { "0": 1, "1": 2, "2": 3 }
```

그러나, 비엄격 함수에서는 **mapped `arguments` 객체**는 함수가 어떤 나머지 매개변수, 기본 매개변수 또는 비구조화된 매개변수든 포함하지 **않는** 경우에만 제공됩니다. 예를 들어, 기본 매개변수를 사용하는 다음 함수에서는, 100 대신에 `10`이 반환됩니다:

```js
function bar(a = 1) {
  arguments[0] = 100;
  return a;
}
bar(10); // 10
```

이 예에서, 어떤 나머지 매개변수, 기본 매개변수 또는 비구조화된 매개변수가 없는 경우에는, 100이 반환됩니다:

```js
function zoo(a) {
  arguments[0] = 100;
  return a;
}
zoo(10); // 100
```

명세
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-arguments-exotic-objects |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `Function`


설정자 - JavaScript

설정자
===

**`set`** 구문은 객체의 속성에 할당을 시도할 때 호출할 함수를 바인딩합니다.

시도해보기
-----

구문
--

```js
{set prop(val) { . . . }}
{set [expression](val) { . . . }}
```

### 매개변수

`prop`

주어진 함수를 바인딩할 속성 이름.

`val`

`prop`에 할당을 시도한 값.

`expression`

ECMAScript 2015 이후, 주어진 함수를 바인딩할 속성 이름을 구하는 표현식을 사용할 수도 있습니다.

설명
--

JavaScript의 설정자(*setter*)를 사용하면 지정한 속성 값의 변경을 시도할 때마다 함수를 호출할 수 있습니다. 설정자는 보통 접근자(*getter*)와 함께 '유사 속성'을 정의할 때 사용합니다. 어떤 속성에 설정자를 바인딩하는 동시에, 해당 속성이 값도 가지도록 할 수는 없습니다.

`set` 구문을 이용할 때는 다음 사항을 주의하세요.

* 설정자의 식별자는 숫자나 문자열일 수 있습니다.
* 설정자 함수는 최대 한 개의 매개변수만 가질 수 있습니다.
* 객체 리터럴에서, 같은 속성 키에 다수의 설정자를 바인딩할 수 없습니다.

```js
{
  set x() { }, set x() { }
}
```

* 객체 리터럴에서, 설정자는 데이터 속성과 같은 키를 사용할 수 없습니다.

```js
{
  x: ..., set x() { }
}
```

예제
--

### 객체 초기자에서 새로운 객체의 설정자 정의하기

다음 예제는 객체 `language`에 유사 속성 `current`를 생성합니다. `current`에 값을 할당하면, 해당 값을 `log` 속성에 저장합니다.

```js
const language = {
  set current(name) {
    this.log.push(name);
  },
  log: [],
};

language.current = "EN";
console.log(language.log); // ['EN']

language.current = "FA";
console.log(language.log); // ['EN', 'FA']
```

`current`의 값은 정의하지 않았으므로, 할당이 아니라 접근을 시도하면 `undefined`만 반환하는 것에 주의하세요.

### `delete` 연산자로 설정자 제거하기

접근자를 삭제하려면 간단히 `delete` (en-US) 연산자를 사용하세요.

```js
delete language.current;
```

### `defineProperty`를 이용해 이미 존재하는 객체에 설정자 정의하기

이미 존재하는 객체에 설정자를 추가하려면 `Object.defineProperty()`를 사용하세요.

```js
const o = { a: 0 };

Object.defineProperty(o, "b", {
  set: function (x) {
    this.a = x / 2;
  },
});

o.b = 10;
// 설정자 실행, a 속성에 10 / 2 = 5 할당

console.log(o.a);
// 5
```

### 계산된 속성 이름 사용하기

```js
const expr = "foo";

const obj = {
  baz: "bar",
  set [expr](v) {
    this.baz = v;
  },
};

console.log(obj.baz);
// "bar"

obj.foo = "baz";
// run the setter

console.log(obj.baz);
// "baz"
```

명세
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-method-definitions |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* 접근자
* `delete` (en-US)
* `Object.defineProperty()`
* `Object.prototype.__defineGetter__()`
* `Object.prototype.__defineSetter__()` (en-US)
* JavaScript 안내서의 접근자와 설정자 정의하기


나머지 매개변수 - JavaScript

나머지 매개변수
========

**나머지 매개변수** 구문을 사용하면 함수가 정해지지 않은 수의 매개변수를 배열로 받을 수 있습니다. JavaScript에서 가변항 함수를 표현할 때 사용합니다.

시도해보기
-----

구문
--

```js
function f(a, b, ...theArgs) {
  // ...
}
```

설명
--

함수의 마지막 매개변수 앞에 "`...`"(세 개의 U+002E FULL STOP 문자)를 붙이면 (사용자가 제공한) 모든 후속 매개변수를 표준 JavaScript 배열에 넣도록 지정합니다. 마지막 매개변수만 나머지 매개변수로 설정할 수 있습니다.

```js
function myFun(a, b, ...manyMoreArgs) {
  console.log("a", a);
  console.log("b", b);
  console.log("manyMoreArgs", manyMoreArgs);
}

myFun("one", "two", "three", "four", "five", "six");

// 콘솔 출력:
// a, one
// b, two
// manyMoreArgs, [three, four, five, six]
```

### 빠른 참조

함수 정의에는 하나의 `...`만 존재할 수 있습니다.

```js
foo(...one, ...wrong, ...wrong);
```

나머지 매개변수는 반드시 함수 정의의 마지막 매개변수여야 합니다.

```js
foo(...wrong, arg2, arg3);
```

```js
foo(arg1, arg2, ...correct);
```

### 나머지 매개변수와 `arguments` 객체의 차이

나머지 매개변수와 `arguments` 객체 사이에는 세 개의 주요 차이가 있습니다.

* `arguments` 객체는 **실제 배열이 아닙니다**. 그러나 나머지 매개변수는 `Array` 인스턴스이므로 `sort`, `map`, `forEach`, `pop` 등의 메서드를 직접 적용할 수 있습니다.
* `arguments` 객체는 `callee` 속성과 같은 추가 기능을 포함합니다.
* `...restParam`은 후속 매개변수만 배열에 포함하므로 `...restParam` **이전**에 직접 정의한 매개변수는 포함하지 않습니다. 그러나 `arguments` 객체는, `...restParam`의 각 항목까지 더해 모든 매개변수를 포함합니다.
### 인수에서 배열로

나머지 매개변수는 다수의 인수를 배열로 변환하는 과정의 보일러플레이트 코드를 줄이기 위해 도입됐습니다.

```js
// 나머지 매개변수 이전에 "arguments"를 일반 배열로 변환하던 방법
function f(a, b) {
  let normalArray = Array.prototype.slice.call(arguments);
  // -- 또는 --
  let normalArray = [].slice.call(arguments);
  // -- 또는 --
  let normalArray = Array.from(arguments);

  let first = normalArray.shift(); // 동작, 첫 번째 매개변수 반환
  let first = arguments.shift(); // 오류, arguments는 실제 배열이 아님
}

// 이제는 나머지 매개변수를 사용해 쉽게 배열로 가져올 수 있음

function f(...args) {
  let normalArray = args;
  let first = normalArray.shift(); // 동작, 첫 번째 매개변수 반환
}
```

예제
--

### 나머지 매개변수 사용하기

아래 예제에서, 첫 번째 인수는 `a`, 두 번째 인수는 `b`로 맵핑되므로 이 두 개의 인수는 일반적인 방법으로 사용할 수 있습니다.

그러나 세 번째 인수인 `manyMoreArgs`는 셋, 넷, 다섯, 여섯, ... n번째 인수까지, 사용자가 제공한 만큼의 인수를 포함한 배열입니다.

```js
function myFun(a, b, ...manyMoreArgs) {
  console.log("a", a);
  console.log("b", b);
  console.log("manyMoreArgs", manyMoreArgs);
}

myFun("one", "two", "three", "four", "five", "six");

// a, "one"
// b, "two"
// manyMoreArgs, ["three", "four", "five", "six"] <-- 배열임에 주목
```

매개변수를 세 개만 제공하더라도 마지막 인수는 여전히 배열인 것을 확인할 수 있습니다.

```js
// 위에 정의한 함수를 그대로 사용

myFun("one", "two", "three");

// a, "one"
// b, "two"
// manyMoreArgs, ["three"] <-- 요소가 하나지만 여전히 배열임
```

그리고 아래에선 매개변수를 두 개만 제공했지만, `manyMoreArgs`는 여전히 (빈) 배열입니다.

```js
// 위에 정의한 함수를 그대로 사용

myFun("one", "two");

// a, "one"
// b, "two"
// manyMoreArgs, [] <-- 여전히 배열
```

### 매개변수 길이

`theArgs`가 배열이므로, `length` 속성을 사용하면 길이를 알아낼 수 있습니다.

```js
function fun1(...theArgs) {
  console.log(theArgs.length);
}

fun1(); // 0
fun1(5); // 1
fun1(5, 6, 7); // 3
```

### 나머지 매개변수를 일반 매개변수와 함께 사용하기

이 예제에서는 첫 번째 이후의 모든 매개변수를 배열에 모은 후, 각각의 값을 첫 번째 매개변수로 곱한 결과를 반환합니다.

```js
function multiply(multiplier, ...theArgs) {
  return theArgs.map((element) => {
    return multiplier \* element;
  });
}

let arr = multiply(2, 15, 25, 42);
console.log(arr); // [30, 50, 84]
```

### 나머지 매개변수는 실제 배열, `arguments`는 유사 배열

나머지 매개변수에서는 `Array` 메서드를 사용할 수 있지만, `arguments` 객체에서는 사용할 수 없습니다.

```js
function sortRestArgs(...theArgs) {
  let sortedArgs = theArgs.sort();
  return sortedArgs;
}

console.log(sortRestArgs(5, 3, 7, 1)); // 1, 3, 5, 7

function sortArguments() {
  let sortedArgs = arguments.sort();
  return sortedArgs;
}

console.log(sortArguments(5, 3, 7, 1));
// TypeError 발생 (arguments.sort is not a function)
```

`arguments` 객체에 `Array` 메서드를 사용하려면 우선 `arguments`를 실제 배열로 변환해야 합니다.

```js
function sortArguments() {
  let args = Array.from(arguments);
  let sortedArgs = args.sort();
  return sortedArgs;
}
console.log(sortArguments(5, 3, 7, 1)); // 1, 3, 5, 7
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-function-definitions |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

함께 보기
-----

* 전개 구문 (같은 '`...`' 사용)
* 구조 분해 할당
* `arguments` 객체
* `Array`


화살표 함수 표현식 - JavaScript

화살표 함수 표현식
==========

화살표 함수 표현식(**화살표 함수 expression**)은 함수 표현식에 대한 간결한 대안으로, 약간의 의미적 차이와 의도적인 사용상의 제한을 가지고 있습니다.

* 화살표 함수에는 자체 바인딩이 `this`에 없으며, `인수` 또는 `super`로 사용해야 하며, 메서드로 사용하면 안 됩니다.
* 화살표 함수는 생성자로 사용할 수 없습니다. `new`로 호출하면 `TypeError`가 반환됩니다. `new.target` 키워드에 대한 액세스 권한도 없습니다.
* 화살표 함수는 함수 내부에서 `yield`를 사용할 수 없으며 제너레이터 함수로 생성할 수 없습니다.
시도해보기
-----

구문
--

```js
() => expression

param => expression

(param) => expression

(param1, paramN) => expression

() => {
  statements
}

param => {
  statements
}

(param1, paramN) => {
  statements
}
```

매개변수 내 나머지 매개변수, 기본값 매개변수, 구조 분해 할당가 지원되며 항상 괄호 안에 넣어야 합니다:

```js
(a, b, ...r) => expression
(a = 400, b = 20, c) => expression
([a, b] = [10, 20]) => expression
({ a, b } = { a: 10, b: 20 }) => expression
```

화살표 함수는 표현식 앞에 `async` 키워드를 붙여서 `async`로 지정할 수 있습니다.

```js
async param => expression
async (param1, param2, ...paramN) => {
  statements
}
```

설명
--

기존의 익명 함수를 가장 간단한 화살표 함수로 단계별로 분해해 보겠습니다. 이 과정에서 각 단계는 유효한 화살표 함수입니다.

**참고:** 기존 함수 표현식과 화살표 함수는 구문 외에도 더 많은 차이점이 있습니다. 다음 몇 개의 하위 섹션에서 두 함수의 동작 차이에 대해 자세히 소개하겠습니다.

```js
// 기존의 익명 함수
(function (a) {
  return a + 100;
});

// 1. "function"이라는 단어를 제거하고 인자와 여는 대괄호 사이에 화살표를 배치합니다.
(a) => {
  return a + 100;
};

// 2. 중괄호와 "return"이라는 단어를 제거하면 반환이 암시됩니다.
(a) => a + 100;

// 3. 매개변수의 괄호를 제거합니다.
a => a + 100;
```

위의 예에서는 매개변수 주위의 괄호와 함수 본문 주위의 중괄호를 모두 생략할 수 있습니다. 그러나 특정 경우에만 생략할 수 있습니다.

괄호는 함수에 하나의 간단한 매개변수가 있는 경우에만 생략할 수 있습니다. 매개 변수가 여러 개 있거나 없거나 기본값인 경우와 구조 분해 할당된 매개 변수 또는 나머지 매개 변수가 있는 경우 매개 변수 목록 주위에 괄호를 사용해야 합니다.

```js
// 기존의 익명 함수
(function (a, b) {
  return a + b + 100;
});

// 화살표 함수
(a, b) => a + b + 100;

const a = 4;
const b = 2;

// 기존의 익명 함수 (매개변수가 없음)
(function () {
  return a + b + 100;
});

// 화살표 함수 (매개변수가 없음)
() => a + b + 100;
```

중괄호는 함수가 직접 표현식을 반환하는 경우에만 생략할 수 있습니다. 본문에 추가로 처리하는 구문이 있는 경우 중괄호가 필요하며 `return` 키워드도 마찬가지입니다. 화살표 함수는 무엇을 언제 반환할지 추측할 수 없습니다.

```js
// 기존의 익명 함수
(function (a, b) {
  const chuck = 42;
  return a + b + chuck;
});

// 화살표 함수
(a, b) => {
  const chuck = 42;
  return a + b + chuck;
};
```

화살표 함수는 항상 이름이 지정되지 않습니다. 화살표 함수가 스스로를 호출해야 하는 경우 명명된 함수 표현식을 대신 사용하세요. 화살표 함수를 변수에 할당하여 이름을 지정할 수도 있습니다.

```js
// 기존 함수
function bob(a) {
  return a + 100;
}

// 화살표 함수
const bob2 = (a) => a + 100;
```

### 함수 내부

화살표 함수는 간결한 본문이나 일반적인 블록 형태의 본문을 가질 수 있습니다.

간결한 본문에서는 암시적 반환값이 되는 단일 표현식만 지정됩니다. 블록 본문에서는 명시적인 `return` 문을 사용해야 합니다.

```js
const func = (x) => x \* x;
// 간결한 본문 구문, 암시적 "반환"

const func2 = (x, y) => {
  return x + y;
};
// 블록 본문을 포함, 명시적 "반환" 필요
```

간결한 본문 구문은 `(params) => { object: literal }`을 사용하여 객체 리터럴을 반환하면 예상대로 작동하지 않습니다.

```js
const func = () => { foo: 1 };
// func()를 호출하면 정의되지 않은 값이 반환됩니다!

const func2 = () => { foo: function () {} };
// SyntaxError: function statement requires a name

const func3 = () => { foo() {} };
// SyntaxError: Unexpected token '{'
```

JavaScript는 화살표 뒤에 오는 토큰이 왼쪽 중괄호가 아닌 경우에만 화살표 함수에 간결한 본문이 있는 것으로 간주합니다. 중괄호({}) 안의 코드는 일련의 구문으로 파싱되며, 여기서 `foo`는 객체 리터럴의 키가 아닌 label이 됩니다.

이 문제를 해결하려면 객체 리터럴을 괄호로 묶으면 됩니다.

```js
const func = () => ({ foo: 1 });
```

### 메서드로 사용할 수 없습니다

화살표 함수 표현식은 `this`가 없기 때문에 메서드가 아닌 함수에만 사용해야 합니다. 메서드로 사용하려고 하면 어떤 일이 일어나는지 살펴봅시다.

```js
"use strict";

const obj = {
  i: 10,
  b: () => console.log(this.i, this),
  c() {
    console.log(this.i, this);
  },
};

obj.b(); // logs undefined, Window { /\* … \*/ } (or the global object)
obj.c(); // logs 10, Object { /\* … \*/ }
```

또 다른 예는 `Object.defineProperty()`와 관련된 것입니다.

```js
"use strict";

const 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'
  },
});
```

클래스의 내부에는 `this`가 있으므로, 화살표 함수는 클래스 필드 (en-US)가 클래스의 `this` 컨텍스트 위에 닫힐 때 작동합니다. 그러면 화살표 함수 내부의 `this`가 인스턴스 (또는 정적 필드의 경우 클래스 자체)를 올바르게 가리키게 됩니다. 그러나 함수 자체의 바인딩이 아닌 클로저이므로 실행 컨텍스트에 따라 `this`의 값이 변경되지 않습니다.

```js
class C {
  a = 1;
  autoBoundMethod = () => {
    console.log(this.a);
  };
}

const c = new C();
c.autoBoundMethod(); // 1
const { autoBoundMethod } = c;
autoBoundMethod(); // 1
// 정상적인 메서드라면 이 경우에는 정의되지 않아야 합니다.
```

화살표 함수 속성은 일반 메서드와 동일하기 때문에 흔히 "자동 바인딩 메서드"라고 불립니다.

```js
class C {
  a = 1;
  constructor() {
    this.method = this.method.bind(this);
  }
  method() {
    console.log(this.a);
  }
}
```

**참고:** 클래스 필드는 프로토타입이 아닌 인스턴스에 정의되므로 인스턴스를 생성할 때마다 새 함수 참조가 생성되고 새 클로저가 할당되어 일반적인 언바운드 메서드보다 메모리 사용량이 늘어날 수 있습니다.

비슷한 이유로 `call()`, `apply()`, `bind()` 메서드는 화살표 함수에서 호출할 때 유용하지 않습니다. 화살표 함수는 화살표 함수가 정의된 범위를 기반으로 `this`을 설정하고 함수가 호출되는 방식에 따라 `this` 값이 변하지 않기 때문입니다.

### 인수의 바인딩이 없습니다

화살표 함수에는 자체 `arguments` 객체가 없습니다. 따라서 이 예제에서 `arguments`는 둘러싸는 범위의 인수를 참조합니다.

```js
function foo(n) {
  const f = () => arguments[0] + n; // foo의 암시적 인자 바인딩입니다. arguments[0]은 n입니다.
  return f();
}

foo(3); // 3 + 3 = 6
```

**참고:** strict mode에서는 `arguments`는 변수를 선언할 수 없으므로 위의 코드는 구문 오류가 됩니다. 이렇게 하면 `arguments`의 범위 지정 효과를 훨씬 더 쉽게 이해할 수 있습니다.

 대부분의 경우, 나머지 매개변수를 사용하는 것이
 `arguments` 객체를 사용하는 것보다 좋은 대안입니다.

```js
function foo(n) {
  const f = (...args) => args[0] + n;
  return f(10);
}

foo(1); // 11
```

### 생성자로 사용할 수 없습니다

화살표 함수는 생성자로 사용할 수 없으며 `new`와 함께 호출하면 에러가 발생합니다. 또한 `prototype` 속성이 없습니다.

```js
const Foo = () => {};
const foo = new Foo(); // TypeError: Foo is not a constructor
console.log("prototype" in Foo); // false
```

### 제너레이터로 사용할 수 없습니다

`yield` 키워드는 화살표 함수 본문에서 사용할 수 없습니다. (화살표 함수 내에 중첩된 제너레이터 함수 내에서 사용하는 경우를 제외하고는요). 따라서 화살표 함수는 제너레이터로 사용할 수 없습니다.

### 화살표 앞 줄 바꿈

화살표 함수에는 매개변수와 화살표 사이에 줄 바꿈이 포함될 수 없습니다.

```js
const func = (a, b, c)
  => 1;
// SyntaxError: Unexpected token '=>'
```

서식을 지정하려면 아래와 같이 화살표 뒤에 줄 바꿈을 넣거나 함수 본문 주위에 괄호/중괄호를 사용할 수 있습니다. 매개변수 사이에 줄 바꿈을 넣을 수도 있습니다.

```js
const func = (a, b, c) =>
  1;

const func2 = (a, b, c) => (
  1
);

const func3 = (a, b, c) => {
  return 1;
};

const func4 = (
  a,
 b,
 c,
) => 1;
```

### 화살표의 우선 순위

화살표 함수의 화살표는 연산자가 아니지만, 화살표 함수에는 일반 함수에 비해 연산자 우선순위가 다른 특수한 구문 분석 규칙이 있습니다.

```js
let callback;

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

`=>`는 대부분의 연산자보다 우선순위가 낮으므로 `callback || ()`이 화살표 함수의 인수 목록으로 구문 분석되지 않도록 괄호를 사용해야 합니다.

```js
callback = callback || (() => {});
```

예제
--

### 화살표 함수 사용하기

```js
// 빈 화살표 함수는 정의되지 않은 값을 반환합니다.
const empty = () => {};

(() => "foobar")();
// "foobar"를 반환합니다.
// (즉시 호출되는 함수 표현식입니다.)

const simple = (a) => (a > 15 ? 15 : a);
simple(16); // 15
simple(10); // 10

const max = (a, b) => (a > b ? a : b);

// 간단한 배열 필터링, 매핑 등
const arr = [5, 6, 13, 0, 1, 18, 23];

const sum = arr.reduce((a, b) => a + b);
// 66

const even = arr.filter((v) => v % 2 === 0);
// [6, 0, 18]

const double = arr.map((v) => v \* 2);
// [10, 12, 26, 0, 2, 36, 46]

// 보다 간결한 프로미스 체인
promise
  .then((a) => {
    // …
  })
  .then((b) => {
    // …
  });

// 시각적으로 더 쉽게 구문 분석할 수 있는 매개변수 없는 화살표 함수
setTimeout(() => {
  console.log("I happen sooner");
  setTimeout(() => {
    // deeper code
    console.log("I happen later");
  }, 1);
}, 1);
```

### call, bind, apply 메서드 사용하기

`call()`, `apply()`, `bind()` 메서드는 각 메서드의 범위를 설정하므로 기존 함수에서 예상되는 대로 작동합니다:

```js
const obj = {
  num: 100,
};

// globalThis에 "num"을 설정하여 사용하지 않는 방법을 표시합니다.
globalThis.num = 42;

// "this"에서 작동하는 간단한 기존 함수
const add = function (a, b, c) {
  return this.num + a + b + c;
};

console.log(add.call(obj, 1, 2, 3)); // 106
console.log(add.apply(obj, [1, 2, 3])); // 106
const boundAdd = add.bind(obj);
console.log(boundAdd(1, 2, 3)); // 106
```

화살표 함수의 경우, `add` 함수는 기본적으로 `globalThis`(전역) 범위에서 생성되므로 `this`가 `globalThis`라고 가정합니다.

```js
const obj = {
  num: 100,
};

// globalThis에 "num"을 설정하여 선택되는 방식을 표시합니다.
globalThis.num = 42;

// 화살표 함수
const add = (a, b, c) => this.num + a + b + c;

console.log(add.call(obj, 1, 2, 3)); // 48
console.log(add.apply(obj, [1, 2, 3])); // 48
const boundAdd = add.bind(obj);
console.log(boundAdd(1, 2, 3)); // 48
```

화살표 함수를 사용하면 가장 큰 이점은 `setTimeout()`, `EventTarget.prototype.addEventListener()`와 같이 함수가 적절한 범위에서 실행되도록 하기 위해 일반적으로 일종의 클로저, `call()`, `apply()` 또는 `bind()`가 필요한 메서드에 사용할 수 있다는 것입니다.

기존 함수 표현식을 사용하면 이와 같은 코드가 예상대로 작동하지 않습니다.

```js
const obj = {
  count: 10,
  doSomethingLater() {
    setTimeout(function () {
      // 함수는 window 범위에서 실행됩니다.
      this.count++;
      console.log(this.count);
    }, 300);
  },
};

obj.doSomethingLater(); // "count" 속성이 window 범위에 없기 때문에 "NaN"을 기록합니다.
```

화살표 함수를 사용하면 `this`의 범위를 더 쉽게 보존할 수 있습니다.

```js
const obj = {
  count: 10,
  doSomethingLater() {
    // 메서드 구문은 "this"를 "obj" 컨텍스트에 바인딩합니다.
    setTimeout(() => {
      // 화살표 함수에는 자체 바인딩이 없고
      // 함수 호출로서 setTimeout은 바인딩 자체를 생성하지 않으므로
      // 외부 메서드의 "obj" 컨텍스트가 사용됩니다.
      this.count++;
      console.log(this.count);
    }, 300);
  },
};

obj.doSomethingLater(); // 11을 기록합니다.
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-arrow-function-definitions |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

참조
--

* 함수
* 함수
* `function`
* `함수` 표현식
* ES6 In Depth: Arrow functions on hacks.mozilla.org (2015)


기본값 매개변수 - JavaScript

기본값 매개변수
========

기본값 함수 매개변수 (**default function parameter**)를 사용하면 값이 전달되지 않거나 `undefined`인 경우 명명된 매개변수를 기본값으로 초기화할 수 있습니다.

시도해보기
-----

구문
--

```js
function fnName(param1 = defaultValue1, /\* …, \*/ paramN = defaultValueN) {
  // …
}
```

설명
--

JavaScript에서, 함수의 매개변수는 ``undefined``가 기본입니다. 그러나, 일부 상황에서는 다른 기본 값을 설정하는 것이 유용할 수 있습니다. 이때가 바로 기본값 매개변수가 필요할 때 입니다.

다음 예제에서 `multiply`가 호출될 때 `b`에 대한 값이 제공되지 않으면 `a * b`를 평가할 때 `b`의 값은 `undefined`가 되고 `multiply`는 `NaN`을 반환합니다.

```js
function multiply(a, b) {
  return a \* b;
}

multiply(5, 2); // 10
multiply(5); // NaN !
```

과거에 기본값을 설정하는 일반적인 방법은 함수 본문에서 매개변수 값을 테스트하고 `undefined`인 경우 값을 할당하는 것이었습니다. 다음 예제에서는 `multiply`가 하나의 인수로만 호출되는 경우 `b`가 `1`로 설정됩니다.

```js
function multiply(a, b) {
  b = typeof b !== "undefined" ? b : 1;
  return a \* b;
}

multiply(5, 2); // 10
multiply(5); // 5
```

기본 매개변수를 사용하면 함수 내부의 검사는 더 이상 필요하지 않습니다. 이제 함수 머리(head)에서 `b`에 `1`을 기본값으로 지정할 수 있습니다.

```js
function multiply(a, b = 1) {
  return a \* b;
}

multiply(5, 2); // 10
multiply(5); // 5
multiply(5, undefined); // 5
```

매개변수는 여전히 왼쪽에서 오른쪽으로 설정되어 나중에 기본값이 없는 매개변수가 있더라도 기본값을 덮어씁니다.

```js
function f(x = 1, y) {
  return [x, y];
}

f(); // [1, undefined]
f(2); // [2, undefined]
```

**참고:** 첫 번째 기본 매개변수와 그 이후의 모든 매개변수는 함수의 `length`에 영향을 미치지 않습니다.

기본 매개변수 생성자는 함수 본문에서 생성된 범위의 상위인 자체 범위에서 동작합니다.

즉, 이전 매개변수는 이후 매개변수의 생성자에서 참조할 수 있습니다. 그러나 함수 본문에 선언된 함수와 변수는 기본값 매개변수 생성자에서 참조할 수 없으며, 이를 시도하면 런타임 `ReferenceError`가 발생합니다. 여기에는 함수 본문에서 `var`로 선언된 변수도 포함됩니다.

예를 들어, 다음 함수는 기본 매개변수 값에 함수 본문의 하위 범위에 대한 접근 권한이 없기 때문에 호출될 때 `ReferenceError`를 발생시킵니다.

```js
function f(a = go()) {
  function go() {
    return ":P";
  }
}

f(); // ReferenceError: go가 정의되지 않았습니다.
```

이 함수는 매개변수 `a`의 값을 출력하는데, 변수 `var a`는 매개변수 목록의 상위 범위가 아닌 함수 본문에 대해 생성된 범위에만 올라가기 때문에 `b`에는 값이 표시되지 않습니다.

```js
function f(a, b = () => console.log(a)) {
  var a = 1;
  b();
}

f(); // undefined
f(5); // 5
```

예제
--

### `undefined` vs 다른 거짓같은 값(falsy values) 전달하기

아래 예제중 두 번째 호출에서, 첫 번째 인수가 명시적으로 `undefined`(`null` 또는 다른 falsy 값은 아니지만)로 설정되어 있어도 여전히 `num` 인수의 값은 여전히 기본값입니다.

```js
function test(num = 1) {
  console.log(typeof num);
}

test(); // 'number' (num은 1로 설정됨)
test(undefined); // 'number' (num이 역시 1로 설정됨)

// 다른 falsy values로 테스트 하기
test(""); // 'string' (num은 ''로 설정됨)
test(null); // 'object' (num은 null로 설정됨)
```

### 호출 시 평가

기본 인수는 호출 시에 평가됩니다. 그래서 Python과 달리 함수가 호출될 때마다 새 객체가 생성됩니다.

```js
function append(value, array = []) {
  array.push(value);
  return array;
}

append(1); // [1]
append(2); // [2], [1, 2]가 아니라
```

이는 심지어 함수와 변수에도 적용됩니다.

```js
function callSomething(thing = something()) {
  return thing;
}

let numberOfTimesCalled = 0;
function something() {
  numberOfTimesCalled += 1;
  return numberOfTimesCalled;
}

callSomething(); // 1
callSomething(); // 2
```

### 이전 매개 변수는 이후 매개 변수의 기본값으로 사용할 수 있습니다

앞서 정의한 매개변수(왼쪽)는 나중에 정의한 매개변수의 기본값으로 사용할 수 있습니다.

```js
function greet(name, greeting, message = `${greeting} ${name}`) {
  return [name, greeting, message];
}

greet("David", "Hi"); // ["David", "Hi", "Hi David"]
greet("David", "Hi", "Happy Birthday!"); // ["David", "Hi", "Happy Birthday!"]
```

이 기능은 다음과 같이 대략적으로 계산할 수 있으며, 이는 처리되는 경계 조건(edge case)의 수를 보여줍니다.

```js
function go() {
  return ":P";
}

function withDefaults(
  a,
 b = 5,
 c = b,
 d = go(),
 e = this,
 f = arguments,
 g = this.value,
) {
  return [a, b, c, d, e, f, g];
}

function withoutDefaults(a, b, c, d, e, f, g) {
  switch (arguments.length) {
    case 0:
    case 1:
      b = 5;
    case 2:
      c = b;
    case 3:
      d = go();
    case 4:
      e = this;
    case 5:
      f = arguments;
    case 6:
      g = this.value;
  }
  return [a, b, c, d, e, f, g];
}

withDefaults.call({ value: "=^\_^=" });
// [undefined, 5, 5, ":P", {value:"=^\_^="}, arguments, "=^\_^="]

withoutDefaults.call({ value: "=^\_^=" });
// [undefined, 5, 5, ":P", {value:"=^\_^="}, arguments, "=^\_^="]
```

### 기본값이 할당된 구조화된 매개변수

구조 분해 할당 구문을 사용하여 기본값 할당을 사용할 수 있습니다.

이를 수행하는 일반적인 방법은 빈 객체/배열을 구조 분해된 매개변수의 기본값으로 설정하는 것입니다.(예: `[x = 1, y = 2] = []`) 이렇게 하면 함수에 아무 것도 전달하지 않고도 해당 값이 미리 채워져 있을 수 있습니다.

```js
function preFilledArray([x = 1, y = 2] = []) {
  return x + y;
}

preFilledArray(); // 3
preFilledArray([]); // 3
preFilledArray([2]); // 4
preFilledArray([2, 3]); // 5

// 객체에서도 동일하게 작동합니다.
function preFilledObject({ z = 3 } = {}) {
  return z;
}

preFilledObject(); // 3
preFilledObject({}); // 3
preFilledObject({ z: 2 }); // 2
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-function-definitions |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

참조
--

* 함수
* 함수
* 나머지 매개변수
* Nullish coalescing operator (`??`)


arguments.callee - JavaScript

arguments.callee
================

**`arguments.callee`** 속성(property)은 현재 실행 중인 함수를 포함합니다.

설명
--

`callee`는 `arguments` 객체의 속성입니다. 그 함수의 몸통(body) 내에서 현재 실행 중인 함수를 참조하는 데 쓰일 수 있습니다. 이는 함수의 이름을 알 수 없는 경우에 유용합니다, 가령 이름 없는 함수 식(또한 "익명 함수"라 함) 내에서.

**경고:** ECMAScript 제5판(ES5) 은 엄격 모드 (en-US)에서 `arguments.callee()`의 사용을 금합니다. function 식(expression)에 이름을 주거나 함수 자체를 호출해야 하는 곳에 function 선언을 사용하여 `arguments.callee()` 사용을 피하세요.

### `arguments.callee`는 왜 ES5 엄격 모드에서 제거되었나요?

(olliej의 Stack Overflow 답변에서 고쳐씀)

초기 버전 JavaScript는 유명(named) 함수 식을 허용하지 않습니다. 그리고 이 때문에 재귀(recursive) 함수 식을 만들 수 없습니다.

예를 들어, 이 구문은 작동됩니다:

```js
function factorial(n) {
  return !(n > 1) ? 1 : factorial(n - 1) \* n;
}

[1, 2, 3, 4, 5].map(factorial);
```

하지만 다음은:

```js
[1, 2, 3, 4, 5].map(function (n) {
  return !(n > 1) ? 1 : /\* what goes here? \*/ (n - 1) \* n;
});
```

아닙니다. 이를 우회하기 위해 `arguments.callee`가 추가되었고 이와 같이 할 수 있습니다

```js
[1, 2, 3, 4, 5].map(function (n) {
  return !(n > 1) ? 1 : arguments.callee(n - 1) \* n;
});
```

그러나, 이는 실로 정말 나쁜 해결책이었습니다. 이는 (다른 `arguments`, `callee` 및 `caller` 문제와 함께) 일반적인 경우에 인라인 및 tail 재귀를 불가능케 하기에 (tracing 등을 통해 선택한 경우에 그것을 달성할 수 있지만 최고의 코드는 검사가 달리 필요하지 않기에 차선입니다.) 다른 주요 문제는 그 재귀 호출이 다른 `this` 값을 갖는 것입니다. 가령:

```js
var global = this;

var sillyFunction = function (recursed) {
  if (!recursed) {
    return arguments.callee(true);
  }
  if (this !== global) {
    alert("This is: " + this);
  } else {
    alert("This is the global");
  }
};

sillyFunction();
```

ECMAScript 3은 유명(named) 함수 식을 허용해서 이 문제를 해결했습니다. 예를 들면:

```js
[1, 2, 3, 4, 5].map(function factorial(n) {
  return !(n > 1) ? 1 : factorial(n - 1) \* n;
});
```

이는 많은 이점이 있습니다:

* 함수는 코드 내부에서 다른 함수처럼 호출될 수 있습니다
* 외부 범위(outer scope)에서 변수를 만들지 않습니다 (IE 8 아래는 제외하고)
* arguments 객체에 액세스하는 것보다 성능이 더 낫습니다

사라지게 됐던 또 다른 기능은 `arguments.callee.caller` 또는 더 명확하게 `Function.caller`였습니다. 이는 왜일까요? 자, 어느 시점에서든 당신은 모든 함수의 스택 상 가장 깊은 caller를 찾을 수 있고 위에서 말했듯이 호출 스택 보기는 한 가지 주요 효과가 있습니다: 이는 큰 수의 최적화를 불가능 또는 훨씬 훨씬 더 어렵게 합니다. 예를 들어, 함수 `f`가 익명(unknown) 함수를 호출하지 않음을 보장할 수 없는 경우, `f`를 인라인하는 게 가능하지 않습니다. 원래 사소하게 인라인 가능했을 지도 모를 모든 호출 사이트가 다수의 guard를 축적함을 뜻합니다:

```js
function f(a, b, c, d, e) {
  return a ? b \* c : d \* e;
}
```

JavaScript 인터프리터가 제공된 모든 인수가 호출이 행해진 그 시점에 숫자임을 보장할 수 없다면, 인라인된 코드 앞에 모든 인수에 대한 검사 삽입이 필요합니다. 그렇지 않으면 그 함수를 인라인할 수 없습니다. 이제 이 특정한 경우에 스마트 인터프리터는 더 최적이고 사용되지 않을 값은 확인하지 않을 검사를 재배열할 수 있어야 합니다. 그러나 많은 경우에 그건 그냥 가능하지 않고 그러므로 인라인은 불가능하게 됩니다.

예
-

### 익명 재귀 함수에서 `arguments.callee` 사용하기

재귀 함수는 자신을 참조할 수 있어야 합니다. 보통, 함수는 그 이름으로 자신을 참조합니다. 그러나, 익명 함수(함수 식 또는 `Function` 생성자로 생성될 수 있는)는 이름이 없습니다. 그러므로 그를 참조하는 액세스 가능한 변수가 없는 경우, 함수가 자신을 참조할 수 있는 유일한 방법은 `arguments.callee`에 의해서입니다.

다음 예는 차례로 팩토리얼 함수를 정의하고 반환하는 함수를 정의합니다. 이 예는 매우 실용적이지 않고 같은 결과가 유명 함수 식으로 달성될 수 없는 경우가 거의 없습니다.

```js
function create() {
  return function (n) {
    if (n <= 1) return 1;
    return n \* arguments.callee(n - 1);
  };
}

var result = create()(5); // 반환값 120 (5 \* 4 \* 3 \* 2 \* 1)
```

### 좋은 대안 없는 `arguments.callee`의 사용

그러나, 다음과 같은 경우에는 `arguments.callee`에 대안이 없습니다. 그래서 그 사라짐(deprecation)은 버그가 될 수 있습니다 (Firefox bug 725398 참조):

```js
function createPerson(sIdentity) {
  var oPerson = new Function("alert(arguments.callee.identity);");
  oPerson.identity = sIdentity;
  return oPerson;
}

var john = createPerson("John Smith");

john();
```

명세
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-arguments-exotic-objects |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

참조
--

* `Function`


arguments[@@iterator]() - JavaScript

arguments[@@iterator]()
=======================

**`@@iterator`** 속성의 초기값은 `Array.prototype.values` 속성의 초기값과 같은 함수 객체입니다.

구문
--
```

arguments[Symbol.iterator]()
```

예제
--

### `for...of` 반복문을 사용한 반복

```js
function f() {
  // 브라우저가 for...of 반복문과
  // for 반복문 안의 let 범위의 변수를 지원해야 합니다.
  for (let letter of arguments) {
    console.log(letter);
  }
}
f("w", "y", "k", "o", "p");
```

명세
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-createunmappedargumentsobject |
| ECMAScript Language Specification # sec-createmappedargumentsobject |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `Array.prototype.values()`


arguments.length - JavaScript

arguments.length
================

**`arguments.length`** 속성은 함수에 전달된 인수의 수를 포함하고 있습니다.

구문
--
```

    arguments.length
```

설명
--

arguments.length 속성은 실제로 함수에 전달된 arguments 의 수를 제공합니다. 이것은 정의된 매개변수의 수보다 작을 수도 클 수도 있습니다. (`Function.length` 보기).

예제
--

### `arguments.length` 사용하기

이 예시에서는 둘 또는 그 이상의 수를 더할 수 있는 함수를 정의합니다.

```js
function adder(base /\*, n2, ... \*/) {
  base = Number(base);
  for (var i = 1; i < arguments.length; i++) {
    base += Number(arguments[i]);
  }
  return base;
}
```

명세
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-arguments-exotic-objects |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `Function`
* `Function.length`


쉼표 연산자 - JavaScript

쉼표 연산자
======

**쉼표 연산자**는 각각의 피연산자를 왼쪽에서 오른쪽 순서로 평가하고, 마지막 연산자의 값을 반환합니다.

시도해보기
-----

구문
--

```js
    expr1, expr2, expr3...
```

### 매개변수

`expr1`, `expr2, expr3...`

아무 표현식.

설명
--

단일 표현식을 요구하는 곳에 복수의 표현식을 사용하고 싶을 때 쉼표 연산자를 사용할 수 있습니다. 가장 흔히 사용되는 곳은 `for` 반복문에 다수의 매개변수를 제공할 때입니다.

쉼표 연산자는 배열, 객체, 함수의 매개변수와 호출 인수에서 사용하는 쉼표와는 전혀 다릅니다.

예제
--

`a`를 한 행에 10개의 요소를 가진 2차원 배열이라고 가정할 때, 아래 예제는 쉼표 연산자를 사용해 한 번에 `i`는 증가시키고 `j`는 감소시킵니다.

다음 코드는 2차원 배열의 대각선에 위치하는 요소의 값을 출력합니다.

```js
for (let i = 0, j = 9; i <= 9; i++, j--) {
  console.log(`a[${i}][${j}] = ${a[i][j]}`);
}
```

쉼표 연산자를 할당에 사용하면, 할당 연산이 표현식에 포함되지 않아 예상한 결과와는 다소 다를 수 있습니다. 다음 예제에서, `a`는 `b = 3`의 값(3)을 할당받지만, `c = 4` 표현식 역시 평가되어 콘솔에 기록됩니다. 연산자 우선순위와 결합성 때문입니다.

```js
var a, b, c;

(a = b = 3), (c = 4); // 콘솔에는 4를 반환
console.log(a); // 3 (제일 왼쪽)

var x, y, z;

x = ((y = 5), (z = 6)); // 콘솔에는 6을 반환
console.log(x); // 6 (제일 오른쪽)
```

### 연산 후 반환

쉼표 연산자를 사용하는 다른 방법은 값을 반환하기 전에 연산을 수행하는 것입니다. 쉼표 연산자는 마지막 표현식의 평가 결과만 반환하지만, 이전 피연산자에 대해서도 평가는 수행하므로 다음과 같은 코드를 작성할 수 있습니다.

```js
function myFunc() {
  var x = 0;

  return (x += 1), x; // ++x 와 같은 효과
}
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-comma-operator |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `for` 반복문


논리적 AND (&&) - JavaScript

논리적 AND (&&)
============

**논리적 AND (`&&`)** (논리적 연결) 연산자는 모든 불리언 피연산자가 `true`가 되었을 때 해당 피연산자의 집합은`true`가
 됩니다.

 보다 일반적으로 왼쪽에서 오른쪽으로 평가할 때 연산자는 처음으로 만나는 거짓 같은 피연산자의
 값을 반환합니다. 혹은 모두 참 같은 값이라면 마지막 피연산자의 값을 반환합니다.

시도해보기
-----

구문
--

```js
expr1 && expr2
```

설명
--

 논리적 AND (`&&`)은 피연산자를 왼쪽에서 오른쪽으로 평가하면서 첫 거짓 같은 피연산자를
 만나면 즉시 그 값을 반환합니다. 만약 모든 값이 참 같은 값이라면 마지막 피연산자의 값이
 반환됩니다.

 만약 어떤 값이 `true`로 변환 가능하다면 그 값은 소위 참 같은 값(truthy)이라
 합니다. 만약 어떤 값이 `false`로 변환 가능하다면 그 값은 소위 거짓 같은 값(falsy)
 이라고 합니다.

거짓으로 변환될 수 있는 표현식의 예제는 아래와 같습니다.

* `false`;
* `null`;
* `NaN`;
* `0`;
* 빈 문자열 (`""` or `''` or ````);
* `undefined`.

AND 연산자는 불리언이 아닌 값을 보존하고 다음과 같이 반환합니다.

```js
result = "" && "foo"; // result 에 ""(빈 문자열)이 할당됩니다
result = 2 && 0; // result 에 0 이 할당됩니다
result = "foo" && 4; // result 에 4 가 할당됩니다.
```

`&&` 연산자는 불리언이 아닌 피연산자와 함께 사용할 수 있지만, 반환 값은 항상 원시형 불리언으로
 변환할 수 있기 때문에 불리언 연산자로 간주합니다. 반환값이나 어떠한 일반적인 표현식을 명시적으로 해당 불리언 값으로 변환하려면 이중
 `NOT 연산자`를 사용하거나
 `Boolean` 생성자를 사용하시기 바랍니다.

### 단락 평가

 논리적 AND 표현식은 단락(short-circuit, 혹은 단축) 연산자입니다. 각 피연산자는 불리언으로 변환되므로, 어떤 변환이
 `false`로 판별되면 AND 연산자는 그 즉시 멈추고 거짓으로 판별된 피연산자의 원래의 값을 반환합니다. 나머지 피연산자는
 평가하지 **않습니다**.

아래 유사 코드를 고려해보세요.
```

(some falsy expression) && expr
```

 첫 번째 피연산자 `(some falsy expression)`은 거짓 같은 값으로 평가되기
 때문에, `expr` 부분은 **절대 평가되지 않습니다**. 만약 `expr`이 함수라면 해당 함수는 절대 실행되지 않습니다.

아래 예제를 참고하세요.

```js
function A() {
  console.log("called A");
  return false;
}
function B() {
  console.log("called B");
  return true;
}

console.log(A() && B());
// 함수 A를 호춣했기 때문에 "called A" 로그가 콘솔에 남습니다.
// && 은 false 를 평가해서 (함수 A는 false를 반한합니다) false이 콘솔에 로깅됩니다.
// AND 연산자는 단락 평가가 가능하기 때문에 함수 B를 무시합니다.
```

### 연산자 우선순위

 AND 연산자는 OR 연산자보다 높은 우선 순위를 가지며, 이는 `&&` 연산자가 `||` 연산자보다 먼저 실행된다는 것을 의미합니다.
 (연산자 우선순위참고).

```js
true || (false && false); // returns true
true && (false || false); // returns false
2 === 3 || (4 < 0 && 1 === 1); // returns false
```

예제
--

### AND 사용하기

다음 코드는 `&&`(논리적 AND) 연산자의 예를 보여줍니다.

```js
a1 = true && true; // t && t returns true
a2 = true && false; // t && f returns false
a3 = false && true; // f && t returns false
a4 = false && 3 === 4; // f && f returns false
a5 = "Cat" && "Dog"; // t && t returns "Dog"
a6 = false && "Cat"; // f && t returns false
a7 = "Cat" && false; // t && f returns false
a8 = "" && false; // f && f returns ""
a9 = false && ""; // f && f returns false
```

### 불리언을 위한 변환 규칙

#### AND를 OR로 변환하기

**불리언**을 포함하는 아래 연산은

```js
bCondition1 && bCondition2;
```

언제나 아래와 같습니다.

```js
!(!bCondition1 || !bCondition2);
```

#### OR을 AND로 변환하기

**불리언**을 포함하는 다음 연산은

```js
bCondition1 || bCondition2;
```

언제나 아래와 같습니다.

```js
!(!bCondition1 && !bCondition2);
```

### 중첩된 괄호 제거

논리적 표현식은 왼쪽에서 오른쪽으로 평가되기 때문에 특정 규칙을 따르는 경우 복잡한 식에서 괄호를 제거할 수 있습니다.

**불리언**을 포함하는 다음 복합적 연산은

```js
bCondition1 || (bCondition2 && bCondition3);
```

언제나 다음과 같습니다.

```js
bCondition1 || (bCondition2 && bCondition3);
```

명세서
---

| Specification |
| --- |
| ECMAScript Language Specification # prod-LogicalANDExpression |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `Boolean`
* Truthy
* Falsy


더하기 할당 (+=) - JavaScript

더하기 할당 (+=)
===========

 더하기 할당 연산자(`+=`)는 오른쪽 피연산자의 값을 변수에 더한 결과를 다시 변수에 할당합니다. 두 피연산자의
 타입이 더하기 할당 연산자의 동작을 결정하며, 덧셈 또는 문자열 연결이 가능합니다.

시도해보기
-----

구문
--

```js
x += y; // x = x + y
```

예제
--

### 더하기 할당 사용하기

```js
// foo = 'foo'
// bar = 5
// baz = true
// 위와 같은 변수를 가정할 때

// Number + Number -> 덧셈
bar += 2; // 7

// Boolean + Number -> 덧셈
baz += 1; // 2

// Boolean + Boolean -> 덧셈
baz += false; // 1

// Number + String -> 연결
bar += "foo"; // "5foo"

// String + Boolean -> 연결
foo += false; // "foofalse"

// String + String -> 연결
foo += "bar"; // "foobar"
```

명세
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-assignment-operators |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* JavaScript 안내서의 할당 연산자
* 더하기 연산자