From a71a000f6ed2613067be9fcf1ff5202cab0a908f Mon Sep 17 00:00:00 2001 From: HoonDongKang Date: Sat, 16 May 2026 02:00:42 +0900 Subject: [PATCH 1/9] =?UTF-8?q?[docs]=2005-data-types/05-array-methods=20?= =?UTF-8?q?=EC=B6=A9=EB=8F=8C=20=ED=95=B4=EA=B2=B0=20=EB=B0=8F=20=EB=B2=88?= =?UTF-8?q?=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../05-data-types/05-array-methods/article.md | 218 +++--------------- 1 file changed, 29 insertions(+), 189 deletions(-) diff --git a/1-js/05-data-types/05-array-methods/article.md b/1-js/05-data-types/05-array-methods/article.md index 550038d9e..f29dd5b6c 100644 --- a/1-js/05-data-types/05-array-methods/article.md +++ b/1-js/05-data-types/05-array-methods/article.md @@ -1,10 +1,6 @@ # 배열과 메서드 -<<<<<<< HEAD 배열은 다양한 메서드를 제공합니다. 학습 편의를 위해 본 챕터에선 배열 메서드를 몇 개의 그룹으로 나눠 소개하도록 하겠습니다. -======= -Arrays provide a lot of methods. To make things easier, in this chapter, they are split into groups. ->>>>>>> upstream/master ## 요소 추가·제거 메서드 @@ -36,19 +32,11 @@ alert( arr.length ); // 3 원하는 대로 요소를 지웠지만 배열의 요소는 여전히 세 개이네요. `arr.length == 3`을 통해 이를 확인할 수 있습니다. -<<<<<<< HEAD 이는 자연스러운 결과입니다. `delete obj.key`는 `key`를 이용해 해당 키에 상응하는 값을 지우기 때문이죠. `delete` 메서드는 제 역할을 다 한 것입니다. 그런데 우리는 삭제된 요소가 만든 빈 공간을 나머지 요소들이 자동으로 채울 것이라 기대하며 이 메서드를 썼습니다. 배열의 길이가 더 짧아지길 기대하며 말이죠. -======= -That's natural, because `delete obj.key` removes a value by the `key`. It's all it does. Fine for objects. But for arrays we usually want the rest of the elements to shift and occupy the freed place. We expect to have a shorter array now. ->>>>>>> upstream/master 이런 기대를 충족하려면 특별한 메서드를 사용해야 합니다. -<<<<<<< HEAD -[arr.splice(start)](mdn:js/Array/splice)는 만능 스위스 맥가이버 칼 같은 메서드입니다. 요소를 자유자재로 다룰 수 있게 해주죠. 이 메서드를 사용하면 요소 추가, 삭제, 교체가 모두 가능합니다. -======= -The [arr.splice](mdn:js/Array/splice) method is a Swiss army knife for arrays. It can do everything: insert, remove and replace elements. ->>>>>>> upstream/master +[arr.splice](mdn:js/Array/splice)는 만능 스위스 맥가이버 칼 같은 메서드입니다. 요소를 자유자재로 다룰 수 있게 해주죠. 이 메서드를 사용하면 요소 추가, 삭제, 교체가 모두 가능합니다. 문법은 다음과 같습니다. @@ -56,11 +44,7 @@ The [arr.splice](mdn:js/Array/splice) method is a Swiss army knife for arrays. I arr.splice(start[, deleteCount, elem1, ..., elemN]) ``` -<<<<<<< HEAD -첫 번째 매개변수는 조작을 가할 첫 번째 요소를 가리키는 `인덱스(index)`입니다. 두 번째 매개변수는 `deleteCount`로, 제거하고자 하는 요소의 개수를 나타냅니다. `elem1, ..., elemN`은 배열에 추가할 요소를 나타냅니다. -======= -It modifies `arr` starting from the index `start`: removes `deleteCount` elements and then inserts `elem1, ..., elemN` at their place. Returns the array of removed elements. ->>>>>>> upstream/master +splice 메서드는 `start` 인덱스부터 `deleteCount` 개의 요소를 제거한 뒤, 그 자리에 `elem1, ..., elemN` 요소를 삽입하여 `arr` 배열을 수정합니다. 그리고 제거된 요소를 담은 배열을 반환합니다. splice 메서드를 사용해 작성된 예시 몇 가지를 보여드리겠습니다. @@ -78,11 +62,7 @@ alert( arr ); // ["I", "JavaScript"] 쉽죠? 인덱스 `1`이 가리키는 요소부터 시작해 요소 한 개(`1`)를 지웠습니다. -<<<<<<< HEAD 다음 예시에선 요소 세 개(3)를 지우고, 그 자리를 다른 요소 두 개로 교체해 보도록 하겠습니다. -======= -In the next example, we remove 3 elements and replace them with the other two: ->>>>>>> upstream/master ```js run let arr = [*!*"I", "study", "JavaScript",*/!* "right", "now"]; @@ -104,11 +84,7 @@ let removed = arr.splice(0, 2); alert( removed ); // "I", "study" <-- 삭제된 요소로 구성된 배열 ``` -<<<<<<< HEAD `splice` 메서드의 `deleteCount`를 `0`으로 설정하면 요소를 제거하지 않으면서 새로운 요소를 추가할 수 있습니다. -======= -The `splice` method is also able to insert the elements without any removals. For that, we need to set `deleteCount` to `0`: ->>>>>>> upstream/master ```js run let arr = ["I", "study", "JavaScript"]; @@ -138,11 +114,7 @@ alert( arr ); // 1,2,3,4,5 ### slice -<<<<<<< HEAD [arr.slice](mdn:js/Array/slice)는 `arr.splice`와 유사해 보이지만 훨씬 간단합니다. -======= -The method [arr.slice](mdn:js/Array/slice) is much simpler than the similar-looking `arr.splice`. ->>>>>>> upstream/master 문법: @@ -152,11 +124,7 @@ arr.slice([start], [end]) 이 메서드는 `"start"` 인덱스부터 (`"end"`를 제외한) `"end"`인덱스까지의 요소를 복사한 새로운 배열을 반환합니다. `start`와 `end`는 둘 다 음수일 수 있는데 이땐, 배열 끝에서부터의 요소 개수를 의미합니다. -<<<<<<< HEAD `arr.slice`는 문자열 메서드인 `str.slice`와 유사하게 동작하는데 `arr.slice`는 서브 문자열(substring) 대신 서브 배열(subarray)을 반환한다는 점이 다릅니다. -======= -It's similar to a string method `str.slice`, but instead of substrings, it makes subarrays. ->>>>>>> upstream/master 예시: @@ -238,11 +206,7 @@ alert( arr.concat(arrayLike) ); // 1,2,something,else 문법: ```js arr.forEach(function(item, index, array) { -<<<<<<< HEAD // 요소에 무언가를 할 수 있습니다. -======= - // ... do something with an item ->>>>>>> upstream/master }); ``` @@ -270,24 +234,14 @@ arr.forEach(function(item, index, array) { ### indexOf, lastIndexOf와 includes -<<<<<<< HEAD -[arr.indexOf](mdn:js/Array/indexOf)와 [arr.lastIndexOf](mdn:js/Array/lastIndexOf), [arr.includes](mdn:js/Array/includes)는 같은 이름을 가진 문자열 메서드와 문법이 동일합니다. 물론 하는 일도 같습니다. 연산 대상이 문자열이 아닌 배열의 요소라는 점만 다릅니다. +[arr.indexOf](mdn:js/Array/indexOf)와 [arr.includes](mdn:js/Array/includes)는 같은 이름을 가진 문자열 메서드와 문법이 유사합니다. 물론 하는 일도 같습니다. 연산 대상이 문자열이 아닌 배열의 요소라는 점만 다릅니다. - `arr.indexOf(item, from)`는 인덱스 `from`부터 시작해 `item(요소)`을 찾습니다. 요소를 발견하면 해당 요소의 인덱스를 반환하고, 발견하지 못했으면 `-1`을 반환합니다. -- `arr.lastIndexOf(item, from)`는 위 메서드와 동일한 기능을 하는데, 검색을 끝에서부터 시작한다는 점만 다릅니다. - `arr.includes(item, from)`는 인덱스 `from`부터 시작해 `item`이 있는지를 검색하는데, 해당하는 요소를 발견하면 `true`를 반환합니다. -예시: -======= -The methods [arr.indexOf](mdn:js/Array/indexOf) and [arr.includes](mdn:js/Array/includes) have the similar syntax and do essentially the same as their string counterparts, but operate on items instead of characters: - -- `arr.indexOf(item, from)` -- looks for `item` starting from index `from`, and returns the index where it was found, otherwise `-1`. -- `arr.includes(item, from)` -- looks for `item` starting from index `from`, returns `true` if found. - -Usually, these methods are used with only one argument: the `item` to search. By default, the search is from the beginning. +일반적으로 위 메서드는 검색할 `item` 하나만 인수로 전달해 호출하며, 기본적으로 검색은 배열의 0번 인덱스부터 시작합니다. -For instance: ->>>>>>> upstream/master +예시: ```js run let arr = [1, 0, false]; @@ -299,23 +253,11 @@ alert( arr.indexOf(null) ); // -1 alert( arr.includes(1) ); // true ``` -<<<<<<< HEAD -위 메서드들은 요소를 찾을 때 완전 항등 연산자 `===` 을 사용한다는 점에 유의하시기 바랍니다. 보시는 바와 같이 `false`를 검색하면 정확히 `false`만을 검색하지, 0을 검색하진 않습니다. +`indexOf` 메서드는 요소를 찾을 때 완전 항등 연산자 `===` 을 사용한다는 점에 유의하시기 바랍니다. 보시는 바와 같이 `false`를 검색하면 정확히 `false`만을 검색하지, 0을 검색하진 않습니다. -요소의 위치를 정확히 알고 싶은게 아니고 요소가 배열 내 존재하는지 여부만 확인하고 싶다면 `arr.includes`를 사용하는 게 좋습니다. +요소의 위치를 정확히 알고 싶은게 아니고 `item`이 배열 내 존재하는지 여부만 확인하고 싶다면 `arr.includes`를 사용하는 게 좋습니다. -`includes`는 `NaN`도 제대로 처리한다는 점에서 `indexOf/lastIndexOf`와 약간의 차이가 있습니다. - -```js run -const arr = [NaN]; -alert( arr.indexOf(NaN) ); // -1 (완전 항등 비교 === 는 NaN엔 동작하지 않으므로 0이 출력되지 않습니다.) -alert( arr.includes(NaN) );// true (NaN의 여부를 확인하였습니다.) -======= -Please note that `indexOf` uses the strict equality `===` for comparison. So, if we look for `false`, it finds exactly `false` and not the zero. - -If we want to check if `item` exists in the array and don't need the index, then `arr.includes` is preferred. - -The method [arr.lastIndexOf](mdn:js/Array/lastIndexOf) is the same as `indexOf`, but looks for from right to left. +[arr.lastIndexOf](mdn:js/Array/lastIndexOf)는 `indexOf`와 동일한 기능을 하는데, 검색을 끝에서부터 시작한다는 점만 다릅니다. ```js run let fruits = ['Apple', 'Orange', 'Apple'] @@ -324,27 +266,20 @@ alert( fruits.indexOf('Apple') ); // 0 (first Apple) alert( fruits.lastIndexOf('Apple') ); // 2 (last Apple) ``` -````smart header="The `includes` method handles `NaN` correctly" -A minor, but noteworthy feature of `includes` is that it correctly handles `NaN`, unlike `indexOf`: +````smart header="`includes` 메서드는 `NaN`을 올바르게 처리합니다" +사소하지만 주목할만한 `includes`의 특징은 `indexOf`와 다르게 `NaN`을 올바르게 처리한다는 점입니다. ```js run const arr = [NaN]; -alert( arr.indexOf(NaN) ); // -1 (wrong, should be 0) -alert( arr.includes(NaN) );// true (correct) ->>>>>>> upstream/master +alert( arr.indexOf(NaN) ); // -1 (0이 출력되지 않습니다.) +alert( arr.includes(NaN) );// true (NaN의 여부를 확인하였습니다.) ``` -That's because `includes` was added to JavaScript much later and uses the more up-to-date comparison algorithm internally. +이는 `includes`가 자바스크립트에 훨씬 나중에 추가되었고 내부적으로 더 최신의 비교 알고리즘을 사용하기 때문입니다. ```` -<<<<<<< HEAD -### find와 findIndex +### find와 findIndex, findLastIndex 객체로 이루어진 배열이 있다고 가정해 봅시다. 특정 조건에 부합하는 객체를 배열 내에서 어떻게 찾을 수 있을까요? -======= -### find and findIndex/findLastIndex - -Imagine we have an array of objects. How do we find an object with a specific condition? ->>>>>>> upstream/master 이럴 때 [arr.find(fn)](mdn:js/Array/find)을 사용할 수 있습니다. @@ -362,11 +297,7 @@ let result = arr.find(function(item, index, array) { - `index` -- 요소의 인덱스 - `array` -- 배열 자기 자신 -<<<<<<< HEAD 함수가 참을 반환하면 탐색은 중단되고 해당 `요소`가 반환됩니다. 원하는 요소를 찾지 못했으면 `undefined`가 반환됩니다. -======= -If it returns `true`, the search is stopped, the `item` is returned. If nothing is found, `undefined` is returned. ->>>>>>> upstream/master `id`와 `name` 프로퍼티를 가진 사용자 객체로 구성된 배열을 예로 들어보겠습니다. 배열 내에서 `id == 1` 조건을 충족하는 사용자 객체를 찾아봅시다. @@ -382,22 +313,15 @@ let user = users.find(item => item.id == 1); alert(user.name); // John ``` -<<<<<<< HEAD 실무에서 객체로 구성된 배열을 다뤄야 할 일이 잦기 때문에 `find` 메서드 활용법을 알아두면 좋습니다. -======= -In real life, arrays of objects are a common thing, so the `find` method is very useful. ->>>>>>> upstream/master 그런데 위 예시에서 `find` 안의 함수가 인자를 하나만 가지고 있다는 점에 주목해주시기 바랍니다(`item => item.id == 1`). 이런 패턴이 가장 많이 사용되는 편입니다. 다른 인자들(`index`, `array`)은 잘 사용되지 않습니다. -<<<<<<< HEAD -[arr.findIndex](mdn:js/Array/findIndex)는 `find`와 동일한 일을 하나, 조건에 맞는 요소를 반환하는 대신 해당 요소의 인덱스를 반환한다는 점이 다릅니다. 조건에 맞는 요소가 없으면 `-1`이 반환됩니다. -======= -The [arr.findIndex](mdn:js/Array/findIndex) method has the same syntax but returns the index where the element was found instead of the element itself. The value of `-1` is returned if nothing is found. +[arr.findIndex](mdn:js/Array/findIndex)는 `find`와 문법이 동일하지만, 조건에 맞는 요소를 반환하는 대신 해당 요소의 인덱스를 반환한다는 점이 다릅니다. 조건에 맞는 요소가 없으면 `-1`이 반환됩니다. -The [arr.findLastIndex](mdn:js/Array/findLastIndex) method is like `findIndex`, but searches from right to left, similar to `lastIndexOf`. +[arr.findLastIndex](mdn:js/Array/findLastIndex)는 `findIndex`와 유사하지만 `lastIndexOf`처럼 검색을 끝에서부터 시작한다는 점이 다릅니다. -Here's an example: +예제: ```js run let users = [ @@ -407,13 +331,12 @@ let users = [ {id: 4, name: "John"} ]; -// Find the index of the first John +// 처음 등장하는 John의 인덱스를 찾습니다. alert(users.findIndex(user => user.name == 'John')); // 0 -// Find the index of the last John +// 마지막으로 등장하는 John의 인덱스를 찾습니다. alert(users.findLastIndex(user => user.name == 'John')); // 3 ``` ->>>>>>> upstream/master ### filter @@ -423,7 +346,6 @@ alert(users.findLastIndex(user => user.name == 'John')); // 3 `filter`는 `find`와 문법이 유사하지만, 조건에 맞는 요소 전체를 담은 배열을 반환한다는 점에서 차이가 있습니다. - ```js let results = arr.filter(function(item, index, array) { // 조건을 충족하는 요소는 results에 순차적으로 더해집니다. @@ -498,12 +420,8 @@ alert( arr ); // *!*1, 15, 2*/!* 기본 정렬 기준 대신 새로운 정렬 기준을 만들려면 `arr.sort()`에 새로운 함수를 넘겨줘야 합니다. -<<<<<<< HEAD 인수로 넘겨주는 함수는 반드시 값 두 개를 비교해야 하고 반환 값도 있어야 합니다. -======= -The function should compare two arbitrary values and return: ->>>>>>> upstream/master ```js function compare(a, b) { if (a > b) return 1; // 첫 번째 값이 두 번째 값보다 큰 경우 @@ -532,19 +450,11 @@ alert(arr); // *!*1, 2, 15*/!* 이제 기대했던 대로 요소가 정렬되었습니다. -<<<<<<< HEAD 여기서 잠시 멈춰 위 예시에서 어떤 일이 일어났는지 생각해 봅시다. 사실 `arr`엔 숫자, 문자열, 객체 등이 들어갈 수 있습니다. 알 수 없는 *무언가*로 구성된 집합이 되는 거죠. 이제 이 비 동질적인 집합을 정렬해야 한다고 가정해봅시다. 무언가를 정렬하려면 기준이 필요하겠죠? 이때 *정렬 기준을 정의해주는 함수(ordering function, 정렬 함수)* 가 필요합니다. `sort`에 정렬 함수를 인수로 넘겨주지 않으면 이 메서드는 사전편집 순으로 요소를 정렬합니다. -`arr.sort(fn)`는 포괄적인 정렬 알고리즘을 이용해 구현되어있습니다. 대개 최적화된 [퀵 소트(quicksort)](https://en.wikipedia.org/wiki/Quicksort)를 사용하는데, `arr.sort(fn)`는 주어진 함수를 사용해 정렬 기준을 만들고 이 기준에 따라 요소들을 재배열하므로 개발자는 내부 정렬 동작 원리를 알 필요가 없습니다. 우리가 해야 할 일은 정렬 함수 `fn`을 만들고 이를 인수로 넘겨주는 것뿐입니다. +`arr.sort(fn)`는 포괄적인 정렬 알고리즘을 이용해 구현되어있습니다. 대개 최적화된 [퀵 소트(quicksort)](https://en.wikipedia.org/wiki/Quicksort) 혹은 [팀 소트(Timsort)](https://en.wikipedia.org/wiki/Timsort)를 사용하는데, `arr.sort(fn)`는 주어진 함수를 사용해 정렬 기준을 만들고 이 기준에 따라 요소들을 재배열하므로 개발자는 내부 정렬 동작 원리를 알 필요가 없습니다. 우리가 해야 할 일은 정렬 함수 `fn`을 만들고 이를 인수로 넘겨주는 것뿐입니다. 정렬 과정에서 어떤 요소끼리 비교가 일어났는지 확인하고 싶다면 아래 코드를 활용하시면 됩니다. -======= -Let's step aside and think about what's happening. The `arr` can be an array of anything, right? It may contain numbers or strings or objects or whatever. We have a set of *some items*. To sort it, we need an *ordering function* that knows how to compare its elements. The default is a string order. - -The `arr.sort(fn)` method implements a generic sorting algorithm. We don't need to care how it internally works (an optimized [quicksort](https://en.wikipedia.org/wiki/Quicksort) or [Timsort](https://en.wikipedia.org/wiki/Timsort) most of the time). It will walk the array, compare its elements using the provided function and reorder them, all we need is to provide the `fn` which does the comparison. - -By the way, if we ever want to know which elements are compared -- nothing prevents us from alerting them: ->>>>>>> upstream/master ```js run [1, -2, 15, 2, 0, 8].sort(function(a, b) { @@ -616,11 +526,7 @@ alert( arr ); // 5,4,3,2,1 [str.split(delim)](mdn:js/String/split)을 이용하면 우리가 원하는 것을 정확히 할 수 있습니다. 이 메서드는 구분자(delimiter) `delim`을 기준으로 문자열을 쪼개줍니다. -<<<<<<< HEAD 아래 예시에선 쉼표와 공백을 합친 문자열이 구분자로 사용되고 있습니다. -======= -In the example below, we split by a comma followed by a space: ->>>>>>> upstream/master ```js run let names = 'Bilbo, Gandalf, Nazgul'; @@ -687,15 +593,9 @@ let value = arr.reduce(function(accumulator, item, index, array) { - `index` -- 요소의 위치 - `array` -- 배열 -<<<<<<< HEAD 이전 함수 호출 결과는 다음 함수를 호출할 때 첫 번째 인수(`previousValue`)로 사용됩니다. 첫 번째 인수는 앞서 호출했던 함수들의 결과가 누적되어 저장되는 '누산기(accumulator)'라고 생각하면 됩니다. 마지막 함수까지 호출되면 이 값은 `reduce`의 반환 값이 됩니다. -======= -As the function is applied, the result of the previous function call is passed to the next one as the first argument. - -So, the first argument is essentially the accumulator that stores the combined result of all previous executions. And at the end, it becomes the result of `reduce`. ->>>>>>> upstream/master 복잡해 보이긴 하지만 예제를 통해 메서드를 이해해 봅시다. @@ -762,13 +662,8 @@ arr.reduce((sum, current) => sum + current); 이런 예외상황 때문에 항상 초깃값을 명시해 줄 것을 권장합니다. -<<<<<<< HEAD [arr.reduceRight](mdn:js/Array/reduceRight)는 `reduce`와 동일한 기능을 하지만 배열의 오른쪽부터 연산을 수행한다는 점이 다른 메서드입니다. -======= -The method [arr.reduceRight](mdn:js/Array/reduceRight) does the same but goes from right to left. ->>>>>>> upstream/master - ## Array.isArray로 배열 여부 알아내기 자바스크립트에서 배열은 독립된 자료형으로 취급되지 않고 객체형에 속합니다. @@ -777,11 +672,7 @@ The method [arr.reduceRight](mdn:js/Array/reduceRight) does the same but goes fr ```js run alert(typeof {}); // object -<<<<<<< HEAD -alert(typeof []); // object -======= -alert(typeof []); // object (same) ->>>>>>> upstream/master +alert(typeof []); // object (동일) ``` 그런데 배열은 자주 사용되는 자료구조이기 때문에 배열인지 아닌지를 감별해내는 특별한 메서드가 있다면 아주 유용할 겁니다. [Array.isArray(value)](mdn:js/Array/isArray)는 이럴 때 사용할 수 있는 유용한 메서드입니다. `value`가 배열이라면 `true`를, 배열이 아니라면 `false`를 반환해주죠. @@ -796,11 +687,7 @@ alert(Array.isArray([])); // true 함수를 호출하는 대부분의 배열 메서드(`find`, `filter`, `map` 등. `sort`는 제외)는 `thisArg`라는 매개변수를 옵션으로 받을 수 있습니다. -<<<<<<< HEAD 자주 사용되는 인수가 아니어서 지금까진 이 매개변수에 대해 언급하지 않았는데, 튜토리얼의 완성도를 위해 `thisArg`에 대해 잠시 언급하고 넘어가도록 하겠습니다. -======= -That parameter is not explained in the sections above, because it's rarely used. But for completeness, we have to cover it. ->>>>>>> upstream/master `thisArg`는 아래와 같이 활용할 수 있습니다. @@ -844,17 +731,12 @@ alert(soldiers[1].age); // 23 `thisArgs`에 `army`를 지정하지 않고 단순히 `users.filter(army.canJoin)`를 사용했다면 `army.canJoin`은 단독 함수처럼 취급되고, 함수 본문 내 `this`는 `undefined`가 되어 에러가 발생했을 겁니다. -<<<<<<< HEAD `users.filter(user => army.canJoin(user))`를 사용하면 `users.filter(army.canJoin, army)`를 대체할 수 있긴 한데 `thisArg`를 사용하는 방식이 좀 더 이해하기 쉬우므로 더 자주 사용됩니다. -======= -A call to `users.filter(army.canJoin, army)` can be replaced with `users.filter(user => army.canJoin(user))`, that does the same. The latter is used more often, as it's a bit easier to understand for most people. ->>>>>>> upstream/master ## 요약 지금까지 살펴본 배열 메서드를 요약해보도록 합시다. -<<<<<<< HEAD - 요소를 더하거나 지우기 - `push(...items)` -- 맨 끝에 요소 추가하기 - `pop()` -- 맨 끝 요소 추출하기 @@ -869,66 +751,31 @@ A call to `users.filter(army.canJoin, army)` can be replaced with `users.filter( - `includes(value)` -- 배열에 `value`가 있으면 `true`를, 그렇지 않으면 `false`를 반환함 - `find/filter(func)` -- `func`의 반환 값을 `true`로 만드는 첫 번째/전체 요소를 반환함 - `findIndex`는 `find`와 유사함. 다만 요소 대신 인덱스를 반환함 -======= -- To add/remove elements: - - `push(...items)` -- adds items to the end, - - `pop()` -- extracts an item from the end, - - `shift()` -- extracts an item from the beginning, - - `unshift(...items)` -- adds items to the beginning. - - `splice(pos, deleteCount, ...items)` -- at index `pos` deletes `deleteCount` elements and inserts `items`. - - `slice(start, end)` -- creates a new array, copies elements from index `start` till `end` (not inclusive) into it. - - `concat(...items)` -- returns a new array: copies all members of the current one and adds `items` to it. If any of `items` is an array, then its elements are taken. - -- To search among elements: - - `indexOf/lastIndexOf(item, pos)` -- look for `item` starting from position `pos`, and return the index or `-1` if not found. - - `includes(value)` -- returns `true` if the array has `value`, otherwise `false`. - - `find/filter(func)` -- filter elements through the function, return first/all values that make it return `true`. - - `findIndex` is like `find`, but returns the index instead of a value. ->>>>>>> upstream/master - 배열 전체 순회하기 - `forEach(func)` -- 모든 요소에 `func`을 호출함. 결과는 반환되지 않음 -<<<<<<< HEAD - 배열 변형하기 - `map(func)` -- 모든 요소에 `func`을 호출하고, 반환된 결과를 가지고 새로운 배열을 만듦 - `sort(func)` -- 배열을 정렬하고 정렬된 배열을 반환함 - `reverse()` -- 배열을 뒤집어 반환함 - `split/join` -- 문자열을 배열로, 배열을 문자열로 변환함 - - `reduce(func, initial)` -- 요소를 차례로 돌면서 `func`을 호출함. 반환값은 다음 함수 호출에 전달함. 최종적으로 하나의 값이 도출됨 + - `reduce/reduceRight(func, initial)` -- 요소를 차례로 돌면서 `func`을 호출함. 반환값은 다음 함수 호출에 전달함. 최종적으로 하나의 값이 도출됨 - 기타 - - `Array.isArray(arr)` -- `arr`이 배열인지 여부를 판단함 -======= -- To transform the array: - - `map(func)` -- creates a new array from results of calling `func` for every element. - - `sort(func)` -- sorts the array in-place, then returns it. - - `reverse()` -- reverses the array in-place, then returns it. - - `split/join` -- convert a string to array and back. - - `reduce/reduceRight(func, initial)` -- calculate a single value over the array by calling `func` for each element and passing an intermediate result between the calls. - -- Additionally: - - `Array.isArray(value)` checks `value` for being an array, if so returns `true`, otherwise `false`. ->>>>>>> upstream/master + - `Array.isArray(arr)` -- `arr`이 배열인지 여부를 판단하고 `true` 혹은 `false`를 반환함 `sort`, `reverse`, `splice`는 기존 배열을 변형시킨다는 점에 주의하시기 바랍니다. 지금까지 배운 메서드만으로 배열과 관련된 작업 99%를 해결할 수 있습니다. 이 외의 배열 메서드도 있긴 한데 잠시 언급하고 넘어가겠습니다. -<<<<<<< HEAD - [arr.some(fn)](mdn:js/Array/some)과 [arr.every(fn)](mdn:js/Array/every)는 배열을 확인합니다. -======= -- [arr.some(fn)](mdn:js/Array/some)/[arr.every(fn)](mdn:js/Array/every) check the array. ->>>>>>> upstream/master - 두 메서드는 `map`과 유사하게 모든 요소를 대상으로 함수를 호출합니다. `some`은 함수의 반환 값을 `true`로 만드는 요소가 하나라도 있는지 여부를 확인하고 `every`는 모든 요소가 함수의 반환 값을 `true`로 만드는지 여부를 확인합니다. 두 메서드 모두 조건을 충족하면 `true`를, 그렇지 않으면 `false`를 반환합니다. + 두 메서드는 `map`과 유사하게 모든 요소를 대상으로 함수 `fn`을 호출합니다. 두 메서드 모두 조건을 충족하면 `true`를, 그렇지 않으면 `false`를 반환합니다. -<<<<<<< HEAD -- [arr.fill(value, start, end)](mdn:js/Array/fill)은 `start`부터 `end`까지 `value`를 채워 넣습니다. -======= - These methods behave sort of like `||` and `&&` operators: if `fn` returns a truthy value, `arr.some()` immediately returns `true` and stops iterating over the rest of items; if `fn` returns a falsy value, `arr.every()` immediately returns `false` and stops iterating over the rest of items as well. + 두 메서드는 `||`와 `&&` 연산자와 비슷하게 동작합니다. 함수 `fn`이 truthy(참 같은 값)를 반환하면 `arr.some()`은 즉시 `true`를 반환하고 나머지 요소에 대한 순회를 중단합니다. 만약 함수 `fn`이 falsy(거짓 같은 값)를 반환하면 `arr.every()`는 즉시 `false`를 반환하고 나머지 요소에 대한 순회를 중단합니다. - We can use `every` to compare arrays: + `every`를 사용하여 다음과 같이 배열을 비교할 수 있습니다. ```js run function arraysEqual(arr1, arr2) { @@ -938,22 +785,15 @@ A call to `users.filter(army.canJoin, army)` can be replaced with `users.filter( alert( arraysEqual([1, 2], [1, 2])); // true ``` -- [arr.fill(value, start, end)](mdn:js/Array/fill) -- fills the array with repeating `value` from index `start` to `end`. ->>>>>>> upstream/master +- [arr.fill(value, start, end)](mdn:js/Array/fill)은 `start`부터 `end`까지 `value`를 채워 넣습니다. - [arr.copyWithin(target, start, end)](mdn:js/Array/copyWithin)은 `start`부터 `end`까지 요소를 복사하고, 복사한 요소를 `target`에 붙여넣습니다. 기존 요소가 있다면 덮어씁니다. -<<<<<<< HEAD +- [arr.flat(depth)](mdn:js/Array/flat)/[arr.flatMap(fn)](mdn:js/Array/flatMap)은 다차원 배열을 새로운 평면 배열로 만듭니다. + 배열에 관한 모든 메서드는 [manual](mdn:js/Array)에서 찾아볼 수 있습니다. 배워야 할 메서드 종류가 너무 많아서 이걸 다 외워야 하나라는 생각이 들 수 있는데, 생각보다 쉬우니 너무 걱정하지 않으셨으면 좋겠습니다. -======= -- [arr.flat(depth)](mdn:js/Array/flat)/[arr.flatMap(fn)](mdn:js/Array/flatMap) create a new flat array from a multidimensional array. - -For the full list, see the [manual](mdn:js/Array). - -At first sight, it may seem that there are so many methods, quite difficult to remember. But actually, that's much easier. ->>>>>>> upstream/master 일단은 요약본을 참고해 자주 사용하는 메서드가 무엇인지 정도만 알아두어도 괜찮습니다. 아래 과제를 풀면서 충분히 연습하다 보면 배열 메서드에 대한 경험치가 쌓일 겁니다. From 92f393e23c8d90d14da4d4045219a5c1eb633a2e Mon Sep 17 00:00:00 2001 From: HoonDongKang Date: Sat, 16 May 2026 02:01:00 +0900 Subject: [PATCH 2/9] =?UTF-8?q?[docs]=2005-data-types/06-iterable=20?= =?UTF-8?q?=EC=B6=A9=EB=8F=8C=20=ED=95=B4=EA=B2=B0=20=EB=B0=8F=20=EB=B2=88?= =?UTF-8?q?=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/05-data-types/06-iterable/article.md | 61 ----------------------- 1 file changed, 61 deletions(-) diff --git a/1-js/05-data-types/06-iterable/article.md b/1-js/05-data-types/06-iterable/article.md index 6dc2fcce1..1988abcf5 100644 --- a/1-js/05-data-types/06-iterable/article.md +++ b/1-js/05-data-types/06-iterable/article.md @@ -2,11 +2,7 @@ *반복 가능한(iterable, 이터러블)* 객체는 배열을 일반화한 객체입니다. 이터러블 이라는 개념을 사용하면 어떤 객체에든 `for..of` 반복문을 적용할 수 있습니다. -<<<<<<< HEAD 배열은 대표적인 이터러블입니다. 배열 외에도 다수의 내장 객체가 반복 가능합니다. 문자열 역시 이터러블의 예입니다. -======= -*Iterable* objects are a generalization of arrays. That's a concept that allows us to make any object useable in a `for..of` loop. ->>>>>>> upstream/master 배열이 아닌 객체가 있는데, 이 객체가 어떤 것들의 컬렉션(목록, 집합 등)을 나타내고 있는 경우, `for..of` 문법을 적용할 수만 있다면 컬렉션을 순회하는데 유용할 겁니다. 이게 가능하도록 해봅시다. @@ -29,21 +25,12 @@ let range = { // for(let num of range) ... num=1,2,3,4,5 ``` -<<<<<<< HEAD `range`를 이터러블로 만들려면(`for..of`가 동작하도록 하려면) 객체에 `Symbol.iterator`(특수 내장 심볼)라는 메서드를 추가해 아래와 같은 일이 벌어지도록 해야 합니다. 1. `for..of`가 시작되자마자 `for..of`는 `Symbol.iterator`를 호출합니다(`Symbol.iterator`가 없으면 에러가 발생합니다). `Symbol.iterator`는 반드시 *이터레이터(iterator, 메서드 `next`가 있는 객체)* 를 반환해야 합니다. 2. 이후 `for..of`는 *반환된 객체(이터레이터)만*을 대상으로 동작합니다. 3. `for..of`에 다음 값이 필요하면, `for..of`는 이터레이터의 `next()`메서드를 호출합니다. 4. `next()`의 반환 값은 `{done: Boolean, value: any}`와 같은 형태이어야 합니다. `done=true`는 반복이 종료되었음을 의미합니다. `done=false`일땐 `value`에 다음 값이 저장됩니다. -======= -To make the `range` object iterable (and thus let `for..of` work) we need to add a method to the object named `Symbol.iterator` (a special built-in symbol just for that). - -1. When `for..of` starts, it calls that method once (or errors if not found). The method must return an *iterator* -- an object with the method `next`. -2. Onward, `for..of` works *only with that returned object*. -3. When `for..of` wants the next value, it calls `next()` on that object. -4. The result of `next()` must have the form `{done: Boolean, value: any}`, where `done=true` means that the loop is finished, otherwise `value` is the next value. ->>>>>>> upstream/master `range`를 반복 가능한 객체로 만들어주는 코드는 다음과 같습니다. @@ -56,13 +43,8 @@ let range = { // 1. for..of 최초 호출 시, Symbol.iterator가 호출됩니다. range[Symbol.iterator] = function() { -<<<<<<< HEAD // Symbol.iterator는 이터레이터 객체를 반환합니다. // 2. 이후 for..of는 반환된 이터레이터 객체만을 대상으로 동작하는데, 이때 다음 값도 정해집니다. -======= - // ...it returns the iterator object: - // 2. Onward, for..of works only with the iterator object below, asking it for next values ->>>>>>> upstream/master return { current: this.from, last: this.to, @@ -157,11 +139,7 @@ for (let char of str) { ## 이터레이터를 명시적으로 호출하기 -<<<<<<< HEAD 이터레이터를 어떻게 명시적으로 사용할 수 있는지 살펴보면서 좀 더 깊게 이해해봅시다. -======= -For deeper understanding, let's see how to use an iterator explicitly. ->>>>>>> upstream/master `for..of`를 사용했을 때와 동일한 방법으로 문자열을 순회할 건데, 이번엔 직접 호출을 통해서 순회해보겠습니다. 다음 코드는 문자열 이터레이터를 만들고, 여기서 값을 '수동으로' 가져옵니다. @@ -186,28 +164,16 @@ while (true) { ## 이터러블과 유사 배열 [#array-like] -<<<<<<< HEAD 비슷해 보이지만 아주 다른 용어 두 가지가 있습니다. 헷갈리지 않으려면 두 용어를 잘 이해하고 있어야 합니다. -======= -Two official terms look similar, but are very different. Please make sure you understand them well to avoid the confusion. ->>>>>>> upstream/master - *이터러블(iterable)* 은 위에서 설명한 바와 같이 메서드 `Symbol.iterator`가 구현된 객체입니다. - *유사 배열(array-like)* 은 인덱스와 `length` 프로퍼티가 있어서 배열처럼 보이는 객체입니다. -<<<<<<< HEAD 브라우저 등의 호스트 환경에서 자바스크립트를 사용해 문제를 해결할 때 이터러블 객체나 유사 배열 객체 혹은 둘 다인 객체를 만날 수 있습니다. -======= -When we use JavaScript for practical tasks in a browser or any other environment, we may meet objects that are iterables or array-likes, or both. ->>>>>>> upstream/master 이터러블 객체(`for..of` 를 사용할 수 있음)이면서 유사배열 객체(숫자 인덱스와 `length` 프로퍼티가 있음)인 문자열이 대표적인 예입니다. -<<<<<<< HEAD 이터러블 객체라고 해서 유사 배열 객체는 아닙니다. 유사 배열 객체라고 해서 이터러블 객체인 것도 아닙니다. -======= -But an iterable may not be array-like. And vice versa an array-like may not be iterable. ->>>>>>> upstream/master 위 예시의 `range`는 이터러블 객체이긴 하지만 인덱스도 없고 `length` 프로퍼티도 없으므로 유사 배열 객체가 아닙니다. @@ -251,13 +217,8 @@ alert(arr.pop()); // World (메서드가 제대로 동작합니다.) 이터러블을 사용한 예시는 다음과 같습니다. -<<<<<<< HEAD ```js // range는 챕터 위쪽 예시에서 그대로 가져왔다고 가정합시다. -======= -```js run -// assuming that range is taken from the example above ->>>>>>> upstream/master let arr = Array.from(range); alert(arr); // 1,2,3,4,5 (배열-문자열 형 변환이 제대로 동작합니다.) ``` @@ -271,13 +232,8 @@ Array.from(obj[, mapFn, thisArg]) 예시: -<<<<<<< HEAD ```js // range는 챕터 위쪽 예시에서 그대로 가져왔다고 가정합시다. -======= -```js run -// assuming that range is taken from the example above ->>>>>>> upstream/master // 각 숫자를 제곱 let arr = Array.from(range, num => num * num); @@ -313,11 +269,7 @@ for (let char of str) { alert(chars); ``` -<<<<<<< HEAD 어쨌든 `Array.from`을 사용한 예시가 더 짧습니다. -======= -...But it is shorter. ->>>>>>> upstream/master `Array.from`을 사용하면 서로게이트 쌍을 처리할 수 있는 `slice`를 직접 구현할 수도 있습니다. @@ -339,29 +291,16 @@ alert( str.slice(1, 3) ); // 쓰레깃값 출력 (영역이 다른 특수 값) `for..of`을 사용할 수 있는 객체를 *이터러블*이라고 부릅니다. -<<<<<<< HEAD - 이터러블엔 메서드 `Symbol.iterator`가 반드시 구현되어 있어야 합니다. - `obj[Symbol.iterator]`의 결과는 *이터레이터*라고 부릅니다. 이터레이터는 이어지는 반복 과정을 처리합니다. - 이터레이터엔 객체 `{done: Boolean, value: any}`을 반환하는 메서드 `next()`가 반드시 구현되어 있어야 합니다. 여기서 `done:true`은 반복이 끝났음을 의미하고 그렇지 않은 경우엔 `value`가 다음 값이 됩니다. - 메서드 `Symbol.iterator`는 `for..of`에 의해 자동으로 호출되는데, 개발자가 명시적으로 호출하는 것도 가능합니다. - 문자열이나 배열 같은 내장 이터러블에도 `Symbol.iterator`가 구현되어 있습니다. - 문자열 이터레이터는 서로게이트 쌍을 지원합니다. -======= -- Technically, iterables must implement the method named `Symbol.iterator`. - - The result of `obj[Symbol.iterator]()` is called an *iterator*. It handles further iteration process. - - An iterator must have the method named `next()` that returns an object `{done: Boolean, value: any}`, here `done:true` denotes the end of the iteration process, otherwise the `value` is the next value. -- The `Symbol.iterator` method is called automatically by `for..of`, but we also can do it directly. -- Built-in iterables like strings or arrays, also implement `Symbol.iterator`. -- String iterator knows about surrogate pairs. ->>>>>>> upstream/master 인덱스와 `length` 프로퍼티가 있는 객체는 *유사 배열*이라 불립니다. 유사 배열 객체엔 다양한 프로퍼티와 메서드가 있을 수 있는데 배열 내장 메서드는 없습니다. 명세서를 보면 대부분의 메서드는 '진짜' 배열이 아닌 이터러블이나 유사 배열을 대상으로 동작한다고 쓰여 있는걸 볼 수 있습니다. 이 방법이 더 추상적이기 때문입니다. -<<<<<<< HEAD `Array.from(obj[, mapFn, thisArg])`을 사용하면 이터러블이나 유사 배열인 `obj`를 진짜 `Array`로 만들 수 있습니다. 이렇게 하면 `obj`에도 배열 메서드를 사용할 수 있죠. 선택 인수 `mapFn`와 `thisArg`는 각 요소에 함수를 적용할 수 있게 해줍니다. -======= -`Array.from(obj[, mapFn, thisArg])` makes a real `Array` from an iterable or array-like `obj`, and we can then use array methods on it. The optional arguments `mapFn` and `thisArg` allow us to apply a function to each item. ->>>>>>> upstream/master From d5e92222b38d9317894c6fa6085b98aaaa5e2148 Mon Sep 17 00:00:00 2001 From: HoonDongKang Date: Sat, 16 May 2026 02:01:21 +0900 Subject: [PATCH 3/9] =?UTF-8?q?[docs]=2005-data-types/07-map-set=20?= =?UTF-8?q?=EC=B6=A9=EB=8F=8C=20=ED=95=B4=EA=B2=B0=20=EB=B0=8F=20=EB=B2=88?= =?UTF-8?q?=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../07-map-set/03-iterable-keys/task.md | 4 - 1-js/05-data-types/07-map-set/article.md | 195 ++++-------------- 2 files changed, 42 insertions(+), 157 deletions(-) diff --git a/1-js/05-data-types/07-map-set/03-iterable-keys/task.md b/1-js/05-data-types/07-map-set/03-iterable-keys/task.md index 7e54dd326..251dee8bd 100644 --- a/1-js/05-data-types/07-map-set/03-iterable-keys/task.md +++ b/1-js/05-data-types/07-map-set/03-iterable-keys/task.md @@ -4,11 +4,7 @@ importance: 5 # 반복 가능한 객체의 키 -<<<<<<< HEAD `map.keys()`를 사용해 배열을 반환받고, 이 배열을 변수에 저장해 `.push`와 같은 배열 메서드를 적용하고 싶다고 해봅시다. -======= -We'd like to get an array of `map.keys()` in a variable and then apply array-specific methods to it, e.g. `.push`. ->>>>>>> upstream/master 작동하지 않네요. diff --git a/1-js/05-data-types/07-map-set/article.md b/1-js/05-data-types/07-map-set/article.md index 4ee6dfa53..e141bc126 100644 --- a/1-js/05-data-types/07-map-set/article.md +++ b/1-js/05-data-types/07-map-set/article.md @@ -1,47 +1,26 @@ # 맵과 셋 -<<<<<<< HEAD 지금까진 아래와 같은 복잡한 자료구조를 학습해 보았습니다. - 객체 -- 키가 있는 컬렉션을 저장함 - 배열 -- 순서가 있는 컬렉션을 저장함 -======= -Till now, we've learned about the following complex data structures: - -- Objects are used for storing keyed collections. -- Arrays are used for storing ordered collections. ->>>>>>> upstream/master 하지만 현실 세계를 반영하기엔 이 두 자료구조 만으론 부족해서 `맵(Map)`과 `셋(Set)`이 등장하게 되었습니다. ## 맵 -<<<<<<< HEAD -[맵(Map)](mdn:js/Map)은 키가 있는 데이터를 저장한다는 점에서 `객체`와 유사합니다. 다만, `맵`은 키에 다양한 자료형을 허용한다는 점에서 차이가 있습니다. -======= -[Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) is a collection of keyed data items, just like an `Object`. But the main difference is that `Map` allows keys of any type. ->>>>>>> upstream/master +[맵(Map)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)은 키가 있는 데이터를 저장한다는 점에서 `객체`와 유사합니다. 다만, `맵`은 키에 다양한 자료형을 허용한다는 점에서 차이가 있습니다. 맵에는 다음과 같은 주요 메서드와 프로퍼티가 있습니다. -<<<<<<< HEAD -- `new Map()` -- 맵을 만듭니다. -- `map.set(key, value)` -- `key`를 이용해 `value`를 저장합니다. -- `map.get(key)` -- `key`에 해당하는 값을 반환합니다. `key`가 존재하지 않으면 `undefined`를 반환합니다. -- `map.has(key)` -- `key`가 존재하면 `true`, 존재하지 않으면 `false`를 반환합니다. -- `map.delete(key)` -- `key`에 해당하는 값을 삭제합니다. -- `map.clear()` -- 맵 안의 모든 요소를 제거합니다. -- `map.size` -- 요소의 개수를 반환합니다. -======= -- [`new Map()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/Map) -- creates the map. -- [`map.set(key, value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set) -- stores the value by the key. -- [`map.get(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get) -- returns the value by the key, `undefined` if `key` doesn't exist in map. -- [`map.has(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has) -- returns `true` if the `key` exists, `false` otherwise. -- [`map.delete(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/delete) -- removes the element (the key/value pair) by the key. -- [`map.clear()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear) -- removes everything from the map. -- [`map.size`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/size) -- returns the current element count. ->>>>>>> upstream/master +- [`new Map()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/Map) -- 맵을 만듭니다. +- [`map.set(key, value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set) -- `key`를 이용해 `value`를 저장합니다. +- [`map.get(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get) -- `key`에 해당하는 값을 반환합니다. `key`가 존재하지 않으면 `undefined`를 반환합니다. +- [`map.has(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has) -- `key`가 존재하면 `true`, 존재하지 않으면 `false`를 반환합니다. +- [`map.delete(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/delete) -- `key`에 해당하는 값을 삭제합니다. +- [`map.clear()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear) -- 맵 안의 모든 요소를 제거합니다. +- [`map.size`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/size) -- 요소의 개수를 반환합니다. 예시: @@ -62,13 +41,8 @@ alert( map.size ); // 3 맵은 객체와 달리 키를 문자형으로 변환하지 않습니다. 키엔 자료형 제약이 없습니다. -<<<<<<< HEAD ```smart header="`map[key]`는 `Map`을 쓰는 바른 방법이 아닙니다." -`map[key] = 2`로 값을 설정하는 것 같이 `map[key]`를 사용할 수 있긴 합니다. 하지만 이 방법은 `map`을 일반 객체처럼 취급하게 됩니다. 따라서 여러 제약이 생기게 되죠. -======= -```smart header="`map[key]` isn't the right way to use a `Map`" -Although `map[key]` also works, e.g. we can set `map[key] = 2`, this is treating `map` as a plain JavaScript object, so it implies all corresponding limitations (only string/symbol keys and so on). ->>>>>>> upstream/master +`map[key] = 2`로 값을 설정하는 것 같이 `map[key]`를 사용할 수 있긴 합니다. 하지만 이 방법은 `map`을 일반 객체처럼 취급하게 됩니다. 따라서 객체의 프로퍼티 키를 문자열 또는 심볼로만 사용할 수 있는 등 여러 제약이 생기게 되죠. `map`을 사용할 땐 `map`전용 메서드 `set`, `get` 등을 사용해야만 합니다. ``` @@ -89,11 +63,7 @@ visitsCountMap.set(john, 123); alert( visitsCountMap.get(john) ); // 123 ``` -<<<<<<< HEAD 객체를 키로 사용할 수 있다는 점은 `맵`의 가장 중요한 기능 중 하나입니다. `객체`에는 문자열 키를 사용할 수 있습니다. 하지만 객체 키는 사용할 수 없습니다. -======= -Using objects as keys is one of the most notable and important `Map` features. The same does not count for `Object`. String as a key in `Object` is fine, but we can't use another `Object` as a key in `Object`. ->>>>>>> upstream/master 객체형 키를 `객체`에 써봅시다. @@ -103,8 +73,8 @@ let ben = { name: "Ben" }; let visitsCountObj = {}; // 객체를 하나 만듭니다. -<<<<<<< HEAD -visitsCountObj[john] = 123; // 객체(john)를 키로 해서 객체에 값(123)을 저장해봅시다. +visitsCountObj[ben] = 234; // 객체(ben)을 키로 사용하겠습니다. +visitsCountObj[john] = 123; // 객체(john)을 키로 사용하면 객체(ben)은 객체(john)으로 덮어써집니다. *!* // 원하는 값(123)을 얻으려면 아래와 같이 키가 들어갈 자리에 `object Object`를 써줘야합니다. @@ -112,19 +82,7 @@ alert( visitsCountObj["[object Object]"] ); // 123 */!* ``` -`visitsCountObj`는 객체이기 때문에 모든 키를 문자형으로 변환시킵니다. 이 과정에서 `john`은 문자형으로 변환되어 `"[object Object]"`가 됩니다. -======= -visitsCountObj[ben] = 234; // try to use ben object as the key -visitsCountObj[john] = 123; // try to use john object as the key, ben object will get replaced - -*!* -// That's what got written! -alert( visitsCountObj["[object Object]"] ); // 123 -*/!* -``` - -As `visitsCountObj` is an object, it converts all `Object` keys, such as `john` and `ben` above, to same string `"[object Object]"`. Definitely not what we want. ->>>>>>> upstream/master +`visitsCountObj`는 객체이기 때문에 모든 `객체`키를 문자형으로 변환시킵니다. 이 과정에서 `john`과 `ben`은 문자형으로 변환되어 `"[object Object]"`가 됩니다. ```smart header="`맵`이 키를 비교하는 방식" `맵`은 [SameValueZero](https://tc39.github.io/ecma262/#sec-samevaluezero)라 불리는 알고리즘을 사용해 값의 등가 여부를 확인합니다. 이 알고리즘은 일치 연산자 `===`와 거의 유사하지만, `NaN`과 `NaN`을 같다고 취급하는 것에서 일치 연산자와 차이가 있습니다. 따라서 맵에선 `NaN`도 키로 쓸 수 있습니다. @@ -142,24 +100,13 @@ map.set('1', 'str1') ``` ```` -<<<<<<< HEAD - ## 맵의 요소에 반복 작업하기 -======= -## Iteration over Map ->>>>>>> upstream/master 다음 세 가지 메서드를 사용해 `맵`의 각 요소에 반복 작업을 할 수 있습니다. -<<<<<<< HEAD -- `map.keys()` -- 각 요소의 키를 모은 반복 가능한(iterable, 이터러블) 객체를 반환합니다. -- `map.values()` -- 각 요소의 값을 모은 이터러블 객체를 반환합니다. -- `map.entries()` -- 요소의 `[키, 값]`을 한 쌍으로 하는 이터러블 객체를 반환합니다. 이 이터러블 객체는 `for..of`반복문의 기초로 쓰입니다. -======= -- [`map.keys()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/keys) -- returns an iterable for keys, -- [`map.values()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/values) -- returns an iterable for values, -- [`map.entries()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/entries) -- returns an iterable for entries `[key, value]`, it's used by default in `for..of`. ->>>>>>> upstream/master +- [`map.keys()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/keys) -- 각 요소의 키를 모은 반복 가능한(iterable, 이터러블) 객체를 반환합니다. +- [`map.values()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/values) -- 각 요소의 값을 모은 이터러블 객체를 반환합니다. +- [`map.entries()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/entries) -- 요소의 `[키, 값]`을 한 쌍으로 하는 이터러블 객체를 반환합니다. 이 이터러블 객체는 `for..of`반복문의 기초로 쓰입니다. 예시: @@ -215,11 +162,7 @@ let map = new Map([ alert( map.get('1') ); // str1 ``` -<<<<<<< HEAD -평범한 객체를 가지고 `맵`을 만들고 싶다면 내장 메서드 [Object.entries(obj)](mdn:js/Object/entries)를 활용해야 합니다. 이 메서드는 객체의 키-값 쌍을 요소(`[key, value]`)로 가지는 배열을 반환합니다. -======= -If we have a plain object, and we'd like to create a `Map` from it, then we can use built-in method [Object.entries(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries) that returns an array of key/value pairs for an object exactly in that format. ->>>>>>> upstream/master +평범한 객체를 가지고 `맵`을 만들고 싶다면 내장 메서드 [Object.entries(obj)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries)를 활용해야 합니다. 이 메서드는 객체의 키-값 쌍을 요소(`[key, value]`)로 가지는 배열을 반환합니다. 예시: @@ -290,29 +233,16 @@ let obj = Object.fromEntries(map); // .entries()를 생략함 ## 셋 -<<<<<<< HEAD -`셋(Set)`은 중복을 허용하지 않는 값을 모아놓은 특별한 컬렉션입니다. 셋에 키가 없는 값이 저장됩니다. -======= -A [`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) is a special type collection - "set of values" (without keys), where each value may occur only once. ->>>>>>> upstream/master +[`셋(Set)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set)은 중복을 허용하지 않는 값을 모아놓은 특별한 컬렉션입니다. 셋에 키가 없는 값이 저장됩니다. 주요 메서드는 다음과 같습니다. -<<<<<<< HEAD -- `new Set(iterable)` -- 셋을 만듭니다. `이터러블` 객체를 전달받으면(대개 배열을 전달받음) 그 안의 값을 복사해 셋에 넣어줍니다. -- `set.add(value)` -- 값을 추가하고 셋 자신을 반환합니다. -- `set.delete(value)` -- 값을 제거합니다. 호출 시점에 셋 내에 값이 있어서 제거에 성공하면 `true`, 아니면 `false`를 반환합니다. -- `set.has(value)` -- 셋 내에 값이 존재하면 `true`, 아니면 `false`를 반환합니다. -- `set.clear()` -- 셋을 비웁니다. -- `set.size` -- 셋에 몇 개의 값이 있는지 세줍니다. -======= -- [`new Set([iterable])`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/Set) -- creates the set, and if an `iterable` object is provided (usually an array), copies values from it into the set. -- [`set.add(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/add) -- adds a value, returns the set itself. -- [`set.delete(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/delete) -- removes the value, returns `true` if `value` existed at the moment of the call, otherwise `false`. -- [`set.has(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/has) -- returns `true` if the value exists in the set, otherwise `false`. -- [`set.clear()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/clear) -- removes everything from the set. -- [`set.size`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/size) -- is the elements count. ->>>>>>> upstream/master +- [`new Set([iterable])`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/Set) -- 셋을 만듭니다. `이터러블` 객체를 전달받으면(대개 배열을 전달받음) 그 안의 값을 복사해 셋에 넣어줍니다. +- [`set.add(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/add) -- 값을 추가하고 셋 자신을 반환합니다. +- [`set.delete(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/delete) -- 값을 제거합니다. 호출 시점에 셋 내에 값이 있어서 제거에 성공하면 `true`, 아니면 `false`를 반환합니다. +- [`set.has(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/has) -- 셋 내에 값이 존재하면 `true`, 아니면 `false`를 반환합니다. +- [`set.clear()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/clear) -- 셋을 비웁니다. +- [`set.size`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/size) -- 셋에 몇 개의 값이 있는지 세줍니다. 셋 내에 동일한 값(value)이 있다면 `set.add(value)`을 아무리 많이 호출하더라도 아무런 반응이 없을 겁니다. 셋 내의 값에 중복이 없는 이유가 바로 이 때문이죠. @@ -342,11 +272,7 @@ for (let user of set) { } ``` -<<<<<<< HEAD -`셋` 대신 배열을 사용하여 방문자 정보를 저장한 후, 중복 값 여부는 배열 메서드인 [arr.find](mdn:js/Array/find)를 이용해 확인할 수도 있습니다. 하지만 `arr.find`는 배열 내 요소 전체를 뒤져 중복 값을 찾기 때문에, 셋보다 성능 면에서 떨어집니다. 반면, `셋`은 값의 유일무이함을 확인하는데 최적화되어있습니다. -======= -The alternative to `Set` could be an array of users, and the code to check for duplicates on every insertion using [arr.find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find). But the performance would be much worse, because this method walks through the whole array checking every element. `Set` is much better optimized internally for uniqueness checks. ->>>>>>> upstream/master +`셋` 대신 배열을 사용하여 방문자 정보를 저장한 후, 중복 값 여부는 배열 메서드인 [arr.find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find)를 이용해 확인할 수도 있습니다. 하지만 `arr.find`는 배열 내 요소 전체를 뒤져 중복 값을 찾기 때문에, 셋보다 성능 면에서 떨어집니다. 반면, `셋`은 값의 유일무이함을 확인하는데 최적화되어있습니다. ## 셋의 값에 반복 작업하기 @@ -365,79 +291,42 @@ set.forEach((value, valueAgain, set) => { 흥미로운 점이 눈에 띄네요. `forEach`에 쓰인 콜백 함수는 세 개의 인수를 받는데, 첫 번째는 `값`, 두 번째도 *같은 값*인 `valueAgain`을 받고 있습니다. 세 번째는 목표하는 객체(셋)이고요. 동일한 값이 인수에 두 번 등장하고 있습니다. -<<<<<<< HEAD 이렇게 구현된 이유는 `맵`과의 호환성 때문입니다. `맵`의 `forEach`에 쓰인 콜백이 세 개의 인수를 받을 때를 위해서죠. 이상해 보이겠지만 이렇게 구현해 놓았기 때문에 `맵`을 `셋`으로 혹은 `셋`을 `맵`으로 교체하기가 쉽습니다. -======= -That's for compatibility with `Map` where the callback passed `forEach` has three arguments. Looks a bit strange, for sure. But this may help to replace `Map` with `Set` in certain cases with ease, and vice versa. ->>>>>>> upstream/master `셋`에도 `맵`과 마찬가지로 반복 작업을 위한 메서드가 있습니다. -<<<<<<< HEAD -- `set.keys()` -- 셋 내의 모든 값을 포함하는 이터러블 객체를 반환합니다. -- `set.values()` -- `set.keys`와 동일한 작업을 합니다. `맵`과의 호환성을 위해 만들어진 메서드입니다. -- `set.entries()` -- 셋 내의 각 값을 이용해 만든 `[value, value]` 배열을 포함하는 이터러블 객체를 반환합니다. `맵`과의 호환성을 위해 만들어졌습니다. -======= -- [`set.keys()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/keys) -- returns an iterable object for values, -- [`set.values()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/values) -- same as `set.keys()`, for compatibility with `Map`, -- [`set.entries()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/entries) -- returns an iterable object for entries `[value, value]`, exists for compatibility with `Map`. ->>>>>>> upstream/master +- [`set.keys()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/keys) -- 셋 내의 모든 값을 포함하는 이터러블 객체를 반환합니다. +- [`set.values()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/values) -- `set.keys`와 동일한 작업을 합니다. `맵`과의 호환성을 위해 만들어진 메서드입니다. +- [`set.entries()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/entries) -- 셋 내의 각 값을 이용해 만든 `[value, value]` 배열을 포함하는 이터러블 객체를 반환합니다. `맵`과의 호환성을 위해 만들어졌습니다. ## 요약 -<<<<<<< HEAD -`맵`은 키가 있는 값이 저장된 컬렉션입니다. -======= -[`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) -- is a collection of keyed values. ->>>>>>> upstream/master +[`맵(Map)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) 은 키가 있는 값이 저장된 컬렉션입니다. 주요 메서드와 프로퍼티: -<<<<<<< HEAD -- `new Map([iterable])` -- 맵을 만듭니다. `[key,value]`쌍이 있는 `iterable`(예: 배열)을 선택적으로 넘길 수 있는데, 이때 넘긴 이터러블 객체는 맵 초기화에 사용됩니다. -- `map.set(key, value)` -- 키를 이용해 값을 저장합니다. -- `map.get(key)` -- 키에 해당하는 값을 반환합니다. `key`가 존재하지 않으면 `undefined`를 반환합니다. -- `map.has(key)` -- 키가 있으면 `true`, 없으면 `false`를 반환합니다. -- `map.delete(key)` -- 키에 해당하는 값을 삭제합니다. -- `map.clear()` -- 맵 안의 모든 요소를 제거합니다. -- `map.size` -- 요소의 개수를 반환합니다. -======= -- [`new Map([iterable])`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/Map) -- creates the map, with optional `iterable` (e.g. array) of `[key,value]` pairs for initialization. -- [`map.set(key, value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set) -- stores the value by the key, returns the map itself. -- [`map.get(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get) -- returns the value by the key, `undefined` if `key` doesn't exist in map. -- [`map.has(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has) -- returns `true` if the `key` exists, `false` otherwise. -- [`map.delete(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/delete) -- removes the element by the key, returns `true` if `key` existed at the moment of the call, otherwise `false`. -- [`map.clear()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear) -- removes everything from the map. -- [`map.size`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/size) -- returns the current element count. ->>>>>>> upstream/master +- [`new Map([iterable])`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/Map) -- 맵을 만듭니다. `[key,value]`쌍이 있는 `iterable`(예: 배열)을 선택적으로 넘길 수 있는데, 이때 넘긴 이터러블 객체는 맵 초기화에 사용됩니다. +- [`map.set(key, value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set) -- 키를 이용해 값을 저장합니다. +- [`map.get(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get) -- 키에 해당하는 값을 반환합니다. `key`가 존재하지 않으면 `undefined`를 반환합니다. +- [`map.has(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has) -- 키가 있으면 `true`, 없으면 `false`를 반환합니다. +- [`map.delete(key)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/delete) -- 키에 해당하는 값을 삭제합니다. +- [`map.clear()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear) -- 맵 안의 모든 요소를 제거합니다. +- [`map.size`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/size) -- 요소의 개수를 반환합니다. 일반적인 `객체`와의 차이점: - 키의 타입에 제약이 없습니다. 객체도 키가 될 수 있습니다. - `size` 프로퍼티 등의 유용한 메서드나 프로퍼티가 있습니다. -<<<<<<< HEAD -`셋`은 중복이 없는 값을 저장할 때 쓰이는 컬렉션입니다. -======= -[`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) -- is a collection of unique values. ->>>>>>> upstream/master +[`셋(Set)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set)은 중복이 없는 값을 저장할 때 쓰이는 컬렉션입니다. 주요 메서드와 프로퍼티: -<<<<<<< HEAD -- `new Set([iterable])` -- 셋을 만듭니다. `iterable` 객체를 선택적으로 전달받을 수 있는데(대개 배열을 전달받음), 이터러블 객체 안의 요소는 셋을 초기화하는데 쓰입니다. -- `set.add(value)` -- 값을 추가하고 셋 자신을 반환합니다. 셋 내에 이미 `value`가 있는 경우 아무런 작업을 하지 않습니다. -- `set.delete(value)` -- 값을 제거합니다. 호출 시점에 셋 내에 값이 있어서 제거에 성공하면 `true`, 아니면 `false`를 반환합니다. -- `set.has(value)` -- 셋 내에 값이 존재하면 `true`, 아니면 `false`를 반환합니다. -- `set.clear()` -- 셋을 비웁니다. -- `set.size` -- 셋에 몇 개의 값이 있는지 세줍니다. -======= -- [`new Set([iterable])`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/Set) -- creates the set, with optional `iterable` (e.g. array) of values for initialization. -- [`set.add(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/add) -- adds a value (does nothing if `value` exists), returns the set itself. -- [`set.delete(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/delete) -- removes the value, returns `true` if `value` existed at the moment of the call, otherwise `false`. -- [`set.has(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/has) -- returns `true` if the value exists in the set, otherwise `false`. -- [`set.clear()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/clear) -- removes everything from the set. -- [`set.size`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/size) -- is the elements count. ->>>>>>> upstream/master +- [`new Set([iterable])`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/Set) -- 셋을 만듭니다. `iterable` 객체를 선택적으로 전달받을 수 있는데(대개 배열을 전달받음), 이터러블 객체 안의 요소는 셋을 초기화하는데 쓰입니다. +- [`set.add(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/add) -- 값을 추가하고 셋 자신을 반환합니다. 셋 내에 이미 `value`가 있는 경우 아무런 작업을 하지 않습니다. +- [`set.delete(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/delete) -- 값을 제거합니다. 호출 시점에 셋 내에 값이 있어서 제거에 성공하면 `true`, 아니면 `false`를 반환합니다. +- [`set.has(value)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/has) -- 셋 내에 값이 존재하면 `true`, 아니면 `false`를 반환합니다. +- [`set.clear()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/clear) -- 셋을 비웁니다. +- [`set.size`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/size) -- 셋에 몇 개의 값이 있는지 세줍니다. `맵`과 `셋`에 반복 작업을 할 땐, 해당 컬렉션에 요소나 값을 추가한 순서대로 반복 작업이 수행됩니다. 따라서 이 두 컬렉션은 정렬이 되어있지 않다고 할 수 없습니다. 그렇지만 컬렉션 내 요소나 값을 재 정렬하거나 (배열에서 인덱스를 이용해 요소를 가져오는 것처럼) 숫자를 이용해 특정 요소나 값을 가지고 오는 것은 불가능합니다. From 75224bf6cc833bf6b747ab3402c126ae4d1653fd Mon Sep 17 00:00:00 2001 From: HoonDongKang Date: Sat, 16 May 2026 02:01:33 +0900 Subject: [PATCH 4/9] =?UTF-8?q?[docs]=2005-data-types/08-weakmap-weakset?= =?UTF-8?q?=20=EC=B6=A9=EB=8F=8C=20=ED=95=B4=EA=B2=B0=20=EB=B0=8F=20?= =?UTF-8?q?=EB=B2=88=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../01-recipients-read/solution.md | 4 - .../08-weakmap-weakset/article.md | 93 +++---------------- 2 files changed, 11 insertions(+), 86 deletions(-) diff --git a/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/solution.md b/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/solution.md index fffaf5854..8a428c77a 100644 --- a/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/solution.md +++ b/1-js/05-data-types/08-weakmap-weakset/01-recipients-read/solution.md @@ -25,11 +25,7 @@ messages.shift(); // 이제 readMessages에는 요소가 하나만 남게 되었습니다(실제 메모리에서 사라지는 건 나중이 되겠지만 말이죠). ``` -<<<<<<< HEAD `위크셋`을 사용하면 메시지를 저장하고 위크셋 내에 메시지가 있는지 여부를 쉽게 확인할 수 있습니다. -======= -The `WeakSet` allows to store a set of messages and easily check for the existence of a message in it. ->>>>>>> upstream/master 위크셋은 자동으로 자신을 청소한다는 장점이 있습니다. 다만 이 장점 때문에 반복 작업이 불가능해서 읽음 상태의 메시지를 '한꺼번에' 가지고 오지 못한다는 단점도 생깁니다. 배열에 저장된 모든 메시지를 대상으로 반복 작업을 수행해 해당 메시지가 위크셋에 저장되어 있는지 확인하면 읽음 상태의 메시지를 '한 번에' 얻어올 수 있습니다. diff --git a/1-js/05-data-types/08-weakmap-weakset/article.md b/1-js/05-data-types/08-weakmap-weakset/article.md index 08638be75..baa3172de 100644 --- a/1-js/05-data-types/08-weakmap-weakset/article.md +++ b/1-js/05-data-types/08-weakmap-weakset/article.md @@ -1,18 +1,8 @@ -<<<<<<< HEAD # 위크맵과 위크셋 에서 배웠듯이 자바스크립트 엔진은 도달 가능한 (그리고 추후 사용될 가능성이 있는) 값을 메모리에 유지합니다. 예시: -======= - -# WeakMap and WeakSet - -As we know from the chapter , JavaScript engine keeps a value in memory while it is "reachable" and can potentially be used. - -For instance: - ->>>>>>> upstream/master ```js let john = { name: "John" }; @@ -40,14 +30,9 @@ let array = [ john ]; john = null; // 참조를 null로 덮어씀 *!* -<<<<<<< HEAD -// john을 나타내는 객체는 배열의 요소이기 때문에 가비지 컬렉터의 대상이 되지 않습니다. +// john이 참조하는 객체가 배열 안에 저장되었습니다. +// 그렇기 때문에 가비지 컬렉터의 대상이 되지 않습니다. // array[0]을 이용하면 해당 객체를 얻는 것도 가능합니다. -======= -// the object previously referenced by john is stored inside the array -// therefore it won't be garbage-collected -// we can get it as array[0] ->>>>>>> upstream/master */!* alert(JSON.stringify(array[0])); ``` @@ -75,21 +60,13 @@ for(let obj of map.keys()){ alert(map.size); ``` -<<<<<<< HEAD -이런 관점에서 `위크맵(WeakMap)`은 일반 `맵`과 전혀 다른 양상을 보입니다. 위크맵을 사용하면 키로 쓰인 객체가 가비지 컬렉션의 대상이 됩니다. -======= -[`WeakMap`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap) is fundamentally different in this aspect. It doesn't prevent garbage-collection of key objects. ->>>>>>> upstream/master +이런 관점에서 [`위크맵(WeakMap)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap)은 일반 `맵`과 전혀 다른 양상을 보입니다. 위크맵을 사용하면 키로 쓰인 객체가 가비지 컬렉션의 대상이 됩니다. 예시를 이용해 이에 대해 자세히 알아보도록 합시다. ## 위크맵 -<<<<<<< HEAD -`맵`과 `위크맵`의 첫 번째 차이는 `위크맵`의 키가 반드시 객체여야 한다는 점입니다. 원시값은 위크맵의 키가 될 수 없습니다. -======= -The first difference between [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) and [`WeakMap`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap) is that keys must be objects, not primitive values: ->>>>>>> upstream/master +[`맵`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)과 [`위크맵`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap)의 첫 번째 차이는 `위크맵`의 키가 반드시 객체여야 한다는 점입니다. 원시값은 위크맵의 키가 될 수 없습니다. ```js run let weakMap = new WeakMap(); @@ -130,15 +107,9 @@ john = null; // 참조를 덮어씀 왜 이렇게 적은 메서드만 제공할까요? 원인은 가비지 컬렉션의 동작 방식 때문입니다. 위 예시의 `john`을 나타내는 객체처럼, 객체는 모든 참조를 잃게 되면 자동으로 가비지 컬렉션의 대상이 됩니다. 그런데 가비지 컬렉션의 *동작 시점*은 정확히 알 수 없습니다. -<<<<<<< HEAD 가비지 컬렉션이 일어나는 시점은 자바스크립트 엔진이 결정합니다. 객체는 모든 참조를 잃었을 때, 그 즉시 메모리에서 삭제될 수도 있고, 다른 삭제 작업이 있을 때까지 대기하다가 함께 삭제될 수도 있습니다. 현재 `위크맵`에 요소가 몇 개 있는지 정확히 파악하는 것 자체가 불가능한 것이죠. 가비지 컬렉터가 한 번에 메모리를 청소할 수도 있고, 부분 부분 메모리를 청소할 수도 있으므로 위크맵의 요소(키/값) 전체를 대상으로 무언가를 하는 메서드는 동작 자체가 불가능합니다. 그럼 위크맵을 어떤 경우에 사용할 수 있을까요? -======= -The JavaScript engine decides that. It may choose to perform the memory cleanup immediately or to wait and do the cleaning later when more deletions happen. So, technically, the current element count of a `WeakMap` is not known. The engine may have cleaned it up or not, or did it partially. For that reason, methods that access all keys/values are not supported. - -Now, where do we need such a data structure? ->>>>>>> upstream/master ## 유스 케이스: 추가 데이터 @@ -182,11 +153,7 @@ countUser(john); // John의 방문 횟수를 증가시킵니다. john = null; ``` -<<<<<<< HEAD 이제 `john`을 나타내는 객체는 가비지 컬렉션의 대상이 되어야 하는데, `visitsCountMap`의 키로 사용되고 있어서 메모리에서 삭제되지 않습니다. -======= -Now, `john` object should be garbage collected, but remains in memory, as it's a key in `visitsCountMap`. ->>>>>>> upstream/master 특정 사용자를 나타내는 객체가 메모리에서 사라지면 해당 객체에 대한 정보(방문 횟수)도 우리가 손수 지워줘야 하는 상황입니다. 이렇게 하지 않으면 `visitsCountMap`가 차지하는 메모리 공간이 한없이 커질 겁니다. 애플리케이션 구조가 복잡할 땐, 이렇게 쓸모 없는 데이터를 수동으로 비워주는 게 꽤 골치 아픕니다. @@ -203,23 +170,13 @@ function countUser(user) { } ``` -<<<<<<< HEAD `위크맵`을 사용해 사용자 방문 횟수를 저장하면 `visitsCountMap`을 수동으로 청소해줄 필요가 없습니다. `john`을 나타내는 객체가 도달 가능하지 않은 상태가 되면 자동으로 메모리에서 삭제되기 때문입니다. `위크맵`의 키(`john`)에 대응하는 값(john의 방문 횟수)도 자동으로 가비지 컬렉션의 대상이 됩니다. -======= -Now we don't have to clean `visitsCountMap`. After `john` object becomes unreachable, by all means except as a key of `WeakMap`, it gets removed from memory, along with the information by that key from `WeakMap`. ->>>>>>> upstream/master ## 유스 케이스: 캐싱 -<<<<<<< HEAD 위크맵은 캐싱(caching)이 필요할 때 유용합니다. 캐싱은 시간이 오래 걸리는 작업의 결과를 저장해서 연산 시간과 비용을 절약해주는 기법입니다. 동일한 함수를 여러 번 호출해야 할 때, 최초 호출 시 반환된 값을 어딘가에 저장해 놓았다가 그다음엔 함수를 호출하는 대신 저장된 값을 사용하는 게 캐싱의 실례입니다. 아래 예시는 함수 연산 결과를 `맵`에 저장하고 있습니다. -======= -Another common example is caching. We can store ("cache") results from a function, so that future calls on the same object can reuse it. - -To achieve that, we can use `Map` (not optimal scenario): ->>>>>>> upstream/master ```js run // 📁 cache.js @@ -257,11 +214,7 @@ alert(cache.size); // 1 (엇! 그런데 객체가 여전히 cache에 남아있 `process(obj)`를 여러 번 호출하면 최초 호출할 때만 연산이 수행되고, 그 이후엔 연산 결과를 `cache`에서 가져옵니다. 그런데 `맵`을 사용하고 있어서 객체가 필요 없어져도 `cache`를 수동으로 청소해 줘야 합니다. -<<<<<<< HEAD `맵`을 `위크맵`으로 교체하면 이런 문제를 예방할 수 있습니다. 객체가 메모리에서 삭제되면, 캐시에 저장된 결과(함수 연산 결과) 역시 메모리에서 자동으로 삭제되기 때문입니다. -======= -If we replace `Map` with `WeakMap`, then this problem disappears. The cached result will be removed from memory automatically after the object gets garbage collected. ->>>>>>> upstream/master ```js run // 📁 cache.js @@ -297,23 +250,13 @@ obj = null; ## 위크셋 -<<<<<<< HEAD -이제 `위크셋(WeakSet)`에 대해 알아봅시다. +이제 [`위크셋(WeakSet)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet)에 대해 알아봅시다. - `위크셋`은 `셋`과 유사한데, 객체만 저장할 수 있다는 점이 다릅니다. 원시값은 저장할 수 없습니다. - 셋 안의 객체는 도달 가능할 때만 메모리에서 유지됩니다. -- `셋`과 마찬가지로 `위크셋`이 지원하는 메서드는 단출합니다. `add`, `has`, `delete`를 사용할 수 있고, `size`, `keys()`나 반복 작업 관련 메서드는 사용할 수 없습니다. +- `셋`과 마찬가지로 `위크셋`이 지원하는 메서드는 단출합니다. [`add`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Weakset/add), [`has`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Weakset/has), [`delete`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Weakset/delete)를 사용할 수 있고, `size`, `keys()`나 반복 작업 관련 메서드는 사용할 수 없습니다. '위크'맵과 유사하게 '위크'셋도 부차적인 데이터를 저장할 때 사용할 수 있습니다. 다만, 위크셋엔 위크맵처럼 복잡한 데이터를 저장하지 않습니다. 대신 "예"나 "아니오" 같은 간단한 답변을 얻는 용도로 사용됩니다. 물론 `위크셋`에 저장되는 값들은 객체이겠죠. -======= -[`WeakSet`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet) behaves similarly: - -- It is analogous to `Set`, but we may only add objects to `WeakSet` (not primitives). -- An object exists in the set while it is reachable from somewhere else. -- Like `Set`, it supports [`add`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Weakset/add), [`has`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Weakset/has) and [`delete`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Weakset/delete), but not `size`, `keys()` and no iterations. - -Being "weak", it also serves as additional storage. But not for arbitrary data, rather for "yes/no" facts. A membership in `WeakSet` may mean something about the object. ->>>>>>> upstream/master 예시와 함께 위크셋의 용도를 알아봅시다. 아래 코드에선 사용자의 사이트 방문 여부를 추적하는 용도로 `위크셋`을 사용하고 있습니다. @@ -341,30 +284,16 @@ john = null; // visitedSet에서 john을 나타내는 객체가 자동으로 삭제됩니다. ``` -<<<<<<< HEAD `위크맵`과 `위크셋`의 가장 큰 단점은 반복 작업이 불가능하다는 점입니다. 위크맵이나 위크셋에 저장된 자료를 한 번에 얻는 게 불가능하죠. 이런 단점은 불편함을 초래하는 것 같아 보이지만, `위크맵`과 `위크셋`을 이용해 할 수 있는 주요 작업을 방해하진 않습니다. `위크맵`과 `위크셋`은 객체와 함께 '추가' 데이터를 저장하는 용도로 쓸 수 있습니다. -======= -The most notable limitation of `WeakMap` and `WeakSet` is the absence of iterations, and the inability to get all current content. That may appear inconvenient, but does not prevent `WeakMap/WeakSet` from doing their main job -- be an "additional" storage of data for objects which are stored/managed at another place. ->>>>>>> upstream/master ## 요약 -<<<<<<< HEAD -`위크맵`은 `맵`과 유사한 컬렉션입니다. `위크맵`을 구성하는 요소의 키는 오직 객체만 가능합니다. 키로 사용된 객체가 메모리에서 삭제되면 이에 대응하는 값 역시 삭제됩니다. - -`위크셋`은 `셋`과 유사한 컬렉션입니다. 위크셋엔 객체만 저장할 수 있습니다. 위크셋에 저장된 객체가 도달 불가능한 상태가 되면 해당 객체는 메모리에서 삭제됩니다. - -두 자료구조 모두 구성 요소 전체를 대상으로 하는 메서드를 지원하지 않습니다. 구성 요소 하나를 대상으로 하는 메서드만 지원합니다. +[`위크맵(WeakMap)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap)은 `맵`과 유사한 컬렉션입니다. `위크맵`을 구성하는 요소의 키는 오직 객체만 가능합니다. 키로 사용된 객체가 메모리에서 삭제되면 이에 대응하는 값 역시 삭제됩니다. -객체엔 '주요' 자료를, `위크맵`과 `위크셋`엔 '부수적인' 자료를 저장하는 형태로 위크맵과 위크셋을 활용할 수 있습니다. 객체가 메모리에서 삭제되면, (그리고 오로지 `위크맵`과 `위크셋`의 키만 해당 객체를 참조하고 있다면) 위크맵이나 위크셋에 저장된 연관 자료들 역시 메모리에서 자동으로 삭제됩니다. -======= -[`WeakMap`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap) is `Map`-like collection that allows only objects as keys and removes them together with associated value once they become inaccessible by other means. - -[`WeakSet`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet) is `Set`-like collection that stores only objects and removes them once they become inaccessible by other means. +[`위크셋(WeakSet)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet)은 `셋`과 유사한 컬렉션입니다. 위크셋엔 객체만 저장할 수 있습니다. 위크셋에 저장된 객체가 도달 불가능한 상태가 되면 해당 객체는 메모리에서 삭제됩니다. -Their main advantages are that they have weak reference to objects, so they can easily be removed by garbage collector. +`위크맵`과 `위크셋`의 가장 큰 장점은 객체에 대한 약한 참조이며, 가비지 컬렉터가 객체를 쉽게 청소할 수 있다는 점입니다. -That comes at the cost of not having support for `clear`, `size`, `keys`, `values`... +하지만 `clear`, `size`, `keys`, `values`와 같은 메서드를 지원하지 않는다는 단점이 있습니다. -`WeakMap` and `WeakSet` are used as "secondary" data structures in addition to the "primary" object storage. Once the object is removed from the primary storage, if it is only found as the key of `WeakMap` or in a `WeakSet`, it will be cleaned up automatically. ->>>>>>> upstream/master +객체엔 '주요' 자료를, `위크맵`과 `위크셋`엔 '부수적인' 자료를 저장하는 형태로 위크맵과 위크셋을 활용할 수 있습니다. 객체가 메모리에서 삭제되면, (그리고 오로지 `위크맵`과 `위크셋`의 키만 해당 객체를 참조하고 있다면) 위크맵이나 위크셋에 저장된 연관 자료들 역시 메모리에서 자동으로 삭제됩니다. From d39a0a00e334067f8832539bc064ec8074b34c55 Mon Sep 17 00:00:00 2001 From: HoonDongKang Date: Sat, 16 May 2026 02:02:15 +0900 Subject: [PATCH 5/9] =?UTF-8?q?[docs]=2005-data-types/09-keys-values-entri?= =?UTF-8?q?es=20=EC=B6=A9=EB=8F=8C=20=ED=95=B4=EA=B2=B0=20=EB=B0=8F=20?= =?UTF-8?q?=EB=B2=88=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../09-keys-values-entries/article.md | 23 ++++--------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/1-js/05-data-types/09-keys-values-entries/article.md b/1-js/05-data-types/09-keys-values-entries/article.md index 6af97ff9b..c9ced331b 100644 --- a/1-js/05-data-types/09-keys-values-entries/article.md +++ b/1-js/05-data-types/09-keys-values-entries/article.md @@ -76,15 +76,9 @@ for (let value of Object.values(user)) { 하지만 `Object.entries`와 `Object.fromEntries`를 순차적으로 적용하면 객체에도 배열 전용 메서드 사용할 수 있습니다. 적용 방법은 다음과 같습니다. -<<<<<<< HEAD 1. `Object.entries(obj)`를 사용해 객체의 키-값 쌍이 요소인 배열을 얻습니다. -2. 1.에서 만든 배열에 `map` 등의 배열 전용 메서드를 적용합니다. +2. 1.에서 만든 배열에 `map` 등의 배열 전용 메서드를 적용해 키-값 쌍을 변환합니다. 3. 2.에서 반환된 배열에 `Object.fromEntries(array)`를 적용해 배열을 다시 객체로 되돌립니다. -======= -1. Use `Object.entries(obj)` to get an array of key/value pairs from `obj`. -2. Use array methods on that array, e.g. `map`, to transform these key/value pairs. -3. Use `Object.fromEntries(array)` on the resulting array to turn it back into an object. ->>>>>>> upstream/master 이 방법을 사용해 가격 정보가 저장된 객체 prices의 프로퍼티 값을 두 배로 늘려보도록 합시다. @@ -97,22 +91,13 @@ let prices = { *!* let doublePrices = Object.fromEntries( -<<<<<<< HEAD - // 객체를 배열로 변환해서 배열 전용 메서드인 map을 적용하고 fromEntries를 사용해 배열을 다시 객체로 되돌립니다. - Object.entries(prices).map(([key, value]) => [key, value * 2]) -======= - // convert prices to array, map each key/value pair into another pair - // and then fromEntries gives back the object + // prices 객체를 배열로 변환하고 각 키-값 쌍에 map을 적용해 새로운 쌍으로 만듭니다. + // 그런 다음 fromEntries를 사용해 배열을 다시 객체로 되돌립니다. Object.entries(prices).map(entry => [entry[0], entry[1] * 2]) ->>>>>>> upstream/master ); */!* alert(doublePrices.meat); // 8 ``` -<<<<<<< HEAD -지금 당장은 어렵게 느껴지겠지만 한두 번 위 방법을 적용해 보면 객체에 배열 전용 메서드를 적용하는게 쉬워질 겁니다. -======= -It may look difficult at first sight, but becomes easy to understand after you use it once or twice. We can make powerful chains of transforms this way. ->>>>>>> upstream/master +지금 당장은 어렵게 느껴지겠지만 한두 번 위 방법을 적용해 보면 객체에 배열 전용 메서드를 적용하는게 쉬워질 겁니다. 이러한 방법으로 변환에 대한 강력한 체인을 만들 수 있습니다. From 55633b5a801bcef83b54e88e22f9eb4053ceb4a0 Mon Sep 17 00:00:00 2001 From: HoonDongKang Date: Sat, 16 May 2026 02:02:26 +0900 Subject: [PATCH 6/9] =?UTF-8?q?[docs]=2005-data-types/10-destructuring-ass?= =?UTF-8?q?ignment=20=EC=B6=A9=EB=8F=8C=20=ED=95=B4=EA=B2=B0=20=EB=B0=8F?= =?UTF-8?q?=20=EB=B2=88=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../10-destructuring-assignment/article.md | 180 +++--------------- 1 file changed, 23 insertions(+), 157 deletions(-) diff --git a/1-js/05-data-types/10-destructuring-assignment/article.md b/1-js/05-data-types/10-destructuring-assignment/article.md index 1f8058dfb..81d00128f 100644 --- a/1-js/05-data-types/10-destructuring-assignment/article.md +++ b/1-js/05-data-types/10-destructuring-assignment/article.md @@ -2,38 +2,22 @@ `객체`와 `배열`은 자바스크립트에서 가장 많이 쓰이는 자료 구조입니다. -<<<<<<< HEAD -키를 가진 데이터 여러 개를 하나의 엔티티에 저장할 땐 객체를, 컬렉션에 데이터를 순서대로 저장할 땐 배열을 사용하죠. +- 키를 가진 데이터 여러 개를 하나의 엔티티에 저장할 땐 객체를 사용합니다. +- 컬렉션에 데이터를 순서대로 저장할 땐 배열을 사용합니다. -개발을 하다 보면 함수에 객체나 배열을 전달해야 하는 경우가 생기곤 합니다. 가끔은 객체나 배열에 저장된 데이터 전체가 아닌 일부만 필요한 경우가 생기기도 하죠. +개발을 하다 보면 함수에 객체나 배열을 전달해야 하는 경우가 생기곤 합니다. 가끔은 객체나 배열에 저장된 데이터 전체가 아닌 특정 요소나 프로퍼티만 필요한 경우가 생기기도 하죠. -이럴 때 객체나 배열을 변수로 '분해'할 수 있게 해주는 특별한 문법인 *구조 분해 할당(destructuring assignment)* 을 사용할 수 있습니다. 이 외에도 함수의 매개변수가 많거나 매개변수 기본값이 필요한 경우 등에서 구조 분해(destructuring)는 그 진가를 발휘합니다. -======= -- Objects allow us to create a single entity that stores data items by key. -- Arrays allow us to gather data items into an ordered list. +이럴 때 객체나 배열을 변수로 '분해'할 수 있게 해주는 특별한 문법인 *구조 분해 할당(destructuring assignment)* 을 사용할 수 있습니다. -However, when we pass these to a function, we may not need all of it. The function might only require certain elements or properties. - -*Destructuring assignment* is a special syntax that allows us to "unpack" arrays or objects into a bunch of variables, as sometimes that's more convenient. - -Destructuring also works well with complex functions that have a lot of parameters, default values, and so on. Soon we'll see that. ->>>>>>> upstream/master +이 외에도 함수의 매개변수가 많거나 매개변수 기본값이 필요한 경우 등에서 구조 분해(destructuring)는 그 진가를 발휘합니다. 그 내용을 만나러 가보죠. ## 배열 분해하기 -<<<<<<< HEAD 배열이 어떻게 변수로 분해되는지 예제를 통해 살펴봅시다. ```js // 이름과 성을 요소로 가진 배열 let arr = ["Bora", "Lee"] -======= -Here's an example of how an array is destructured into variables: - -```js -// we have an array with a name and surname -let arr = ["John", "Smith"] ->>>>>>> upstream/master *!* // 구조 분해 할당을 이용해 @@ -42,38 +26,24 @@ let arr = ["John", "Smith"] let [firstName, surname] = arr; */!* -<<<<<<< HEAD alert(firstName); // Bora alert(surname); // Lee -======= -alert(firstName); // John -alert(surname); // Smith ->>>>>>> upstream/master ``` 이제 인덱스를 이용해 배열에 접근하지 않고도 변수로 이름과 성을 사용할 수 있게 되었습니다. 아래 예시처럼 `split` 같은 반환 값이 배열인 메서드를 함께 활용해도 좋습니다. -<<<<<<< HEAD -```js +```js run let [firstName, surname] = "Bora Lee".split(' '); +alert(firstName); // Bora +alert(surname); // Lee ``` +보다시피 문법은 간단합니다. 하지만 몇 가지 특징이 있습니다. 아래 예제를 살펴봅시다. + ````smart header="'분해(destructuring)'는 '파괴(destructive)'를 의미하지 않습니다." 구조 분해 할당이란 명칭은 어떤 것을 복사한 이후에 변수로 '분해(destructurize)'해준다는 의미 때문에 붙여졌습니다. 이 과정에서 분해 대상은 수정 또는 파괴되지 않습니다. -======= -```js run -let [firstName, surname] = "John Smith".split(' '); -alert(firstName); // John -alert(surname); // Smith -``` - -As you can see, the syntax is simple. There are several peculiar details though. Let's see more examples to understand it better. - -````smart header="\"Destructuring\" does not mean \"destructive\"." -It's called "destructuring assignment," because it "destructurizes" by copying items into variables. However, the array itself is not modified. ->>>>>>> upstream/master 배열의 요소를 직접 변수에 할당하는 것보다 코드 양이 줄어든다는 점만 다릅니다. ```js @@ -95,11 +65,7 @@ let [firstName, , title] = ["Julius", "Caesar", "Consul", "of the Roman Republic alert( title ); // Consul ``` -<<<<<<< HEAD 두 번째 요소는 생략되었지만, 세 번째 요소는 `title`이라는 변수에 할당된 것을 확인할 수 있습니다. 할당할 변수가 없기 때문에 네 번째 요소 역시 생략되었습니다. -======= -In the code above, the second element of the array is skipped, the third one is assigned to `title`, and the rest of the array items are also skipped (as there are no variables for them). ->>>>>>> upstream/master ```` ````smart header="할당 연산자 우측엔 모든 이터러블이 올 수 있습니다." @@ -114,44 +80,26 @@ That works, because internally a destructuring assignment works by iterating ove ```` -<<<<<<< HEAD ````smart header="할당 연산자 좌측엔 뭐든지 올 수 있습니다." 할당 연산자 좌측엔 '할당할 수 있는(assignables)' 것이라면 어떤 것이든 올 수 있습니다. -======= -````smart header="Assign to anything on the left-side" -We can use any "assignables" on the left side. ->>>>>>> upstream/master 아래와 같이 객체 프로퍼티도 가능합니다. ```js run let user = {}; -<<<<<<< HEAD [user.name, user.surname] = "Bora Lee".split(' '); alert(user.name); // Bora -======= -[user.name, user.surname] = "John Smith".split(' '); - -alert(user.name); // John -alert(user.surname); // Smith ->>>>>>> upstream/master +alert(user.surname); // Lee ``` ```` -<<<<<<< HEAD ````smart header=".entries()로 반복하기" [Object.entries(obj)](mdn:js/Object/entries)는 이전 챕터에서 학습한 바 있습니다. 이 메서드와 구조 분해를 조합하면 객체의 키와 값을 순회해 변수로 분해 할당할 수 있습니다. -======= -````smart header="Looping with .entries()" -In the previous chapter, we saw the [Object.entries(obj)](mdn:js/Object/entries) method. - -We can use it with destructuring to loop over the keys-and-values of an object: ->>>>>>> upstream/master ```js run let user = { @@ -159,11 +107,7 @@ let user = { age: 30 }; -<<<<<<< HEAD // 객체의 키와 값 순회하기 -======= -// loop over the keys-and-values ->>>>>>> upstream/master *!* for (let [key, value] of Object.entries(user)) { */!* @@ -171,11 +115,7 @@ for (let [key, value] of Object.entries(user)) { } ``` -<<<<<<< HEAD -맵에도 물론 이 메서드를 활용할 수 있습니다. -======= -The similar code for a `Map` is simpler, as it's iterable: ->>>>>>> upstream/master +`Map`은 이터러블이므로 코드를 더 간단히 작성할 수 있습니다. ```js run let user = new Map(); @@ -191,24 +131,15 @@ for (let [key, value] of user) { ``` ```` -<<<<<<< HEAD ```smart header="변수 교환 트릭" 두 변수에 저장된 값을 교환할 때 구조 분해 할당을 사용할 수 있습니다. -======= -````smart header="Swap variables trick" -There's a well-known trick for swapping values of two variables using a destructuring assignment: ->>>>>>> upstream/master ```js run let guest = "Jane"; let admin = "Pete"; -<<<<<<< HEAD // 변수 guest엔 Pete, 변수 admin엔 Jane이 저장되도록 값을 교환함 -======= -// Let's swap the values: make guest=Pete, admin=Jane *!* ->>>>>>> upstream/master [guest, admin] = [admin, guest]; */!* @@ -217,69 +148,48 @@ alert(`${guest} ${admin}`); // Pete Jane(값 교환이 성공적으로 이뤄졌 예시에선 임시 배열을 만들어 두 변수를 담고, 요소 순서를 교체해 배열을 분해하는 방식을 사용했습니다. -<<<<<<< HEAD 이 방식을 사용하면 두 개뿐만 아니라 그 이상의 변수에 담긴 값도 교환할 수 있습니다. -======= -We can swap more than two variables this way. -```` ->>>>>>> upstream/master ### '...'로 나머지 요소 가져오기 -<<<<<<< HEAD -배열 앞쪽에 위치한 값 몇 개만 필요하고 그 이후 이어지는 나머지 값들은 한데 모아서 저장하고 싶을 때가 있습니다. 이럴 때는 점 세 개 `...`를 붙인 매개변수 하나를 추가하면 '나머지(rest)' 요소를 가져올 수 있습니다. -======= -Usually, if the array is longer than the list at the left, the "extra" items are omitted. +분해하고자 하는 배열의 길이가 할당하고자 하는 변수의 개수보다 크다면 길이를 '초과(extra)'한 요소는 생략됩니다. -For example, here only two items are taken, and the rest is just ignored: +아래 예제에서는 두 개의 요소만 할당되고 나머지 요소들은 무시됩니다. ```js run let [name1, name2] = ["Julius", "Caesar", "Consul", "of the Roman Republic"]; alert(name1); // Julius alert(name2); // Caesar -// Further items aren't assigned anywhere +// 이후의 요소는 할당되지 않습니다. ``` -If we'd like also to gather all that follows -- we can add one more parameter that gets "the rest" using three dots `"..."`: ->>>>>>> upstream/master +이어지는 나머지 값들을 모두 모아서 저장하고 싶다면, 점 세 개 `...`를 붙인 매개변수 하나를 추가하여 '나머지(rest)' 요소를 가져올 수 있습니다. ```js run let [name1, name2, *!*...rest*/!*] = ["Julius", "Caesar", *!*"Consul", "of the Roman Republic"*/!*]; *!* -<<<<<<< HEAD -// `rest`는 배열입니다. -======= -// rest is an array of items, starting from the 3rd one ->>>>>>> upstream/master +// rest는 세 번째 요소부터 담은 배열입니다. alert(rest[0]); // Consul alert(rest[1]); // of the Roman Republic alert(rest.length); // 2 */!* ``` -<<<<<<< HEAD -`rest`는 나머지 배열 요소들이 저장된 새로운 배열이 됩니다. `rest` 대신에 다른 이름을 사용해도 되는데, 변수 앞의 점 세 개(`...`)와 변수가 가장 마지막에 위치해야 한다는 점은 지켜주시기 바랍니다. -======= -The value of `rest` is the array of the remaining array elements. +`rest`는 나머지 배열 요소들이 저장된 새로운 배열이 됩니다. -We can use any other variable name in place of `rest`, just make sure it has three dots before it and goes last in the destructuring assignment. +`rest` 대신에 다른 이름을 사용해도 되는데, 변수 앞의 점 세 개(`...`)와 변수가 가장 마지막에 위치해야 한다는 점은 지켜주시기 바랍니다. ```js run let [name1, name2, *!*...titles*/!*] = ["Julius", "Caesar", "Consul", "of the Roman Republic"]; // now titles = ["Consul", "of the Roman Republic"] ``` ->>>>>>> upstream/master ### 기본값 -<<<<<<< HEAD 할당하고자 하는 변수의 개수가 분해하고자 하는 배열의 길이보다 크더라도 에러가 발생하지 않습니다. 할당할 값이 없으면 undefined로 취급되기 때문입니다. -======= -If the array is shorter than the list of variables on the left, there will be no errors. Absent values are considered undefined: ->>>>>>> upstream/master ```js run *!* @@ -304,11 +214,7 @@ alert(surname); // Anonymous (기본값) 복잡한 표현식이나 함수 호출도 기본값이 될 수 있습니다. 이렇게 기본식으로 표현식이나 함수를 설정하면 할당할 값이 없을 때 표현식이 평가되거나 함수가 호출됩니다. -<<<<<<< HEAD -기본값으로 두 개의 `prompt` 함수를 할당한 예시를 살펴봅시다. 값이 제공되지 않았을 때만 함수가 호출되므로, `prompt`는 한 번만 호출됩니다. -======= -For instance, here we use the `prompt` function for two defaults: ->>>>>>> upstream/master +기본값으로 두 개의 `prompt` 함수를 할당한 예시를 살펴봅시다. ```js run // name의 prompt만 실행됨 @@ -318,7 +224,7 @@ alert(surname); // 김 (배열에서 받아온 값) alert(name); // prompt에서 받아온 값 ``` -Please note: the `prompt` will run only for the missing value (`surname`). +참고로 `prompt`는 누락된 값인 `surname`에 대해서만 실행됩니다. ## 객체 분해하기 @@ -330,11 +236,7 @@ Please note: the `prompt` will run only for the missing value (`surname`). let {var1, var2} = {var1:…, var2:…} ``` -<<<<<<< HEAD 할당 연산자 우측엔 분해하고자 하는 객체를, 좌측엔 상응하는 객체 프로퍼티의 '패턴'을 넣습니다. 분해하려는 객체 프로퍼티의 키 목록을 패턴으로 사용하는 예시를 살펴봅시다. -======= -We should have an existing object on the right side, that we want to split into variables. The left side contains an object-like "pattern" for corresponding properties. In the simplest case, that's a list of variable names in `{...}`. ->>>>>>> upstream/master 예시: @@ -354,13 +256,9 @@ alert(width); // 100 alert(height); // 200 ``` -<<<<<<< HEAD -프로퍼티 `options.title`과 `options.width`, `options.height`에 저장된 값이 상응하는 변수에 할당된 것을 확인할 수 있습니다. 참고로 순서는 중요하지 않습니다. 아래와 같이 작성해도 위 예시와 동일하게 동작합니다. -======= -Properties `options.title`, `options.width` and `options.height` are assigned to the corresponding variables. +프로퍼티 `options.title`과 `options.width`, `options.height`에 저장된 값이 상응하는 변수에 할당된 것을 확인할 수 있습니다. -The order does not matter. This works too: ->>>>>>> upstream/master +참고로 순서는 중요하지 않습니다. 아래와 같이 작성해도 위 예시와 동일하게 동작합니다. ```js // let {...} 안의 순서가 바뀌어도 동일하게 동작함 @@ -369,11 +267,7 @@ let {height, width, title} = { title: "Menu", height: 200, width: 100 } 할당 연산자 좌측엔 좀 더 복잡한 패턴이 올 수도 있습니다. 분해하려는 객체의 프로퍼티와 변수의 연결을 원하는 대로 조정할 수도 있습니다. -<<<<<<< HEAD 객체 프로퍼티를 프로퍼티 키와 다른 이름을 가진 변수에 저장해봅시다. `options.width`를 `w`라는 변수에 저장하는 식으로 말이죠. 좌측 패턴에 콜론(:)을 사용하면 원하는 목표를 달성할 수 있습니다. -======= -If we want to assign a property to a variable with another name, for instance, make `options.width` go into the variable named `w`, then we can set the variable name using a colon: ->>>>>>> upstream/master ```js run let options = { @@ -526,15 +420,9 @@ alert( title ); // Menu ## 중첩 구조 분해 -<<<<<<< HEAD 객체나 배열이 다른 객체나 배열을 포함하는 경우, 좀 더 복잡한 패턴을 사용하면 중첩 배열이나 객체의 정보를 추출할 수 있습니다. 이를 중첩 구조 분해(nested destructuring)라고 부릅니다. 아래 예시에서 객체 `options`의 `size` 프로퍼티 값은 또 다른 객체입니다. `items` 프로퍼티는 배열을 값으로 가지고 있습니다. 대입 연산자 좌측의 패턴은 정보를 추출하려는 객체 `options`와 같은 구조를 갖추고 있습니다. -======= -If an object or an array contains other nested objects and arrays, we can use more complex left-side patterns to extract deeper portions. - -In the code below `options` has another object in the property `size` and an array in the property `items`. The pattern on the left side of the assignment has the same structure to extract values from them: ->>>>>>> upstream/master ```js run let options = { @@ -563,11 +451,7 @@ alert(item1); // Cake alert(item2); // Donut ``` -<<<<<<< HEAD `extra`(할당 연산자 좌측의 패턴에는 없음)를 제외한 `options` 객체의 모든 프로퍼티가 상응하는 변수에 할당되었습니다. -======= -All properties of `options` object except `extra` which is absent in the left part, are assigned to corresponding variables: ->>>>>>> upstream/master ![](destructuring-complex.svg) @@ -577,15 +461,9 @@ All properties of `options` object except `extra` which is absent in the left pa ## 똑똑한 함수 매개변수 -<<<<<<< HEAD 함수에 매개변수가 많은데 이중 상당수는 선택적으로 쓰이는 경우가 종종 있습니다. 사용자 인터페이스와 연관된 함수에서 이런 상황을 자주 볼 수 있죠. 메뉴 생성에 관여하는 함수가 있다고 해 봅시다. 메뉴엔 너비, 높이, 제목, 항목 리스트 등이 필요하기 때문에 이 정보는 매개변수로 받습니다. 먼저 리팩토링 전의 메뉴 생성 함수를 살펴보겠습니다. -======= -There are times when a function has many parameters, most of which are optional. That's especially true for user interfaces. Imagine a function that creates a menu. It may have a width, a height, a title, an item list and so on. - -Here's a bad way to write such a function: ->>>>>>> upstream/master ```js function showMenu(title = "Untitled", width = 200, height = 100, items = []) { @@ -593,11 +471,7 @@ function showMenu(title = "Untitled", width = 200, height = 100, items = []) { } ``` -<<<<<<< HEAD 이렇게 함수를 작성하면 넘겨주는 인수의 순서가 틀려 문제가 발생할 수 있습니다. 문서화가 잘 되어있다면 IDE가 순서를 틀리지 않게 도움을 주긴 하겠지만 말이죠. 이 외에도 대부분의 매개변수에 기본값이 설정되어 있어 굳이 인수를 넘겨주지 않아도 되는 경우에 문제가 발생합니다. -======= -In real-life, the problem is how to remember the order of arguments. Usually, IDEs try to help us, especially if the code is well-documented, but still... Another problem is how to call a function when most parameters are ok by default. ->>>>>>> upstream/master 아래 코드를 살펴보시죠. 어떤 느낌이 드시나요? @@ -662,11 +536,7 @@ function({ }) ``` -<<<<<<< HEAD 매개변수로 전달된 객체의 프로퍼티 `incomingProperty`는 `varName`에 할당되겠죠. 만약 값이 없다면 `defaultValue`가 기본값으로 사용될 겁니다. -======= -Then, for an object of parameters, there will be a variable `varName` for the property `incomingProperty`, with `defaultValue` by default. ->>>>>>> upstream/master 참고로 이렇게 함수 매개변수를 구조 분해할 땐, 반드시 인수가 전달된다고 가정되고 사용된다는 점에 유의하시기 바랍니다. 모든 인수에 기본값을 할당해 주려면 빈 객체를 명시적으로 전달해야 합니다. @@ -706,10 +576,6 @@ showMenu(); // Menu 100 200 let [item1 = defaultValue, item2, ...rest] = array ``` -<<<<<<< HEAD array의 첫 번째 요소는 `item1`에, 두 번째 요소는 변수 `item2`에 할당되고, 이어지는 나머지 요소들은 배열 `rest` 저장됩니다. -======= - The first item goes to `item1`; the second goes into `item2`, and all the rest makes the array `rest`. ->>>>>>> upstream/master - 할당 연산자 좌측의 패턴과 우측의 구조가 같으면 중첩 배열이나 객체가 있는 복잡한 구조에서도 원하는 데이터를 뽑아낼 수 있습니다. From fe6345ef76463fe5346501c5343c5cb5bc50bed3 Mon Sep 17 00:00:00 2001 From: HoonDongKang Date: Sat, 16 May 2026 23:26:54 +0900 Subject: [PATCH 7/9] =?UTF-8?q?[fix]=20=EB=B2=88=EC=97=AD=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/05-data-types/05-array-methods/article.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/1-js/05-data-types/05-array-methods/article.md b/1-js/05-data-types/05-array-methods/article.md index f29dd5b6c..0307c3b15 100644 --- a/1-js/05-data-types/05-array-methods/article.md +++ b/1-js/05-data-types/05-array-methods/article.md @@ -239,7 +239,7 @@ arr.forEach(function(item, index, array) { - `arr.indexOf(item, from)`는 인덱스 `from`부터 시작해 `item(요소)`을 찾습니다. 요소를 발견하면 해당 요소의 인덱스를 반환하고, 발견하지 못했으면 `-1`을 반환합니다. - `arr.includes(item, from)`는 인덱스 `from`부터 시작해 `item`이 있는지를 검색하는데, 해당하는 요소를 발견하면 `true`를 반환합니다. -일반적으로 위 메서드는 검색할 `item` 하나만 인수로 전달해 호출하며, 기본적으로 검색은 배열의 0번 인덱스부터 시작합니다. +일반적으로 위 두 메서드는 검색할 `item` 하나만 인수로 전달해 호출하며, 기본적으로 검색은 배열의 0번 인덱스부터 시작합니다. 예시: @@ -731,7 +731,7 @@ alert(soldiers[1].age); // 23 `thisArgs`에 `army`를 지정하지 않고 단순히 `users.filter(army.canJoin)`를 사용했다면 `army.canJoin`은 단독 함수처럼 취급되고, 함수 본문 내 `this`는 `undefined`가 되어 에러가 발생했을 겁니다. -`users.filter(user => army.canJoin(user))`를 사용하면 `users.filter(army.canJoin, army)`를 대체할 수 있긴 한데 `thisArg`를 사용하는 방식이 좀 더 이해하기 쉬우므로 더 자주 사용됩니다. +`users.filter(army.canJoin, army)`는 `users.filter(user => army.canJoin(user))`로 대체할 수 있습니다. 두 방식은 동일하게 동작하지만, 후자가 좀 더 이해하기 쉬우므로 더 자주 사용됩니다. ## 요약 From 942156bccbf84958ab64a99f46b9c01a358e25c7 Mon Sep 17 00:00:00 2001 From: HoonDongKang Date: Sat, 16 May 2026 23:50:07 +0900 Subject: [PATCH 8/9] =?UTF-8?q?[fix]=20=EB=B2=88=EC=97=AD=20=EB=88=84?= =?UTF-8?q?=EB=9D=BD=20=EB=B6=80=EB=B6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/05-data-types/06-iterable/article.md | 4 ++-- 1-js/05-data-types/10-destructuring-assignment/article.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/1-js/05-data-types/06-iterable/article.md b/1-js/05-data-types/06-iterable/article.md index 1988abcf5..cb20b848f 100644 --- a/1-js/05-data-types/06-iterable/article.md +++ b/1-js/05-data-types/06-iterable/article.md @@ -217,7 +217,7 @@ alert(arr.pop()); // World (메서드가 제대로 동작합니다.) 이터러블을 사용한 예시는 다음과 같습니다. -```js +```js run // range는 챕터 위쪽 예시에서 그대로 가져왔다고 가정합시다. let arr = Array.from(range); alert(arr); // 1,2,3,4,5 (배열-문자열 형 변환이 제대로 동작합니다.) @@ -232,7 +232,7 @@ Array.from(obj[, mapFn, thisArg]) 예시: -```js +```js run // range는 챕터 위쪽 예시에서 그대로 가져왔다고 가정합시다. // 각 숫자를 제곱 diff --git a/1-js/05-data-types/10-destructuring-assignment/article.md b/1-js/05-data-types/10-destructuring-assignment/article.md index 81d00128f..286e58128 100644 --- a/1-js/05-data-types/10-destructuring-assignment/article.md +++ b/1-js/05-data-types/10-destructuring-assignment/article.md @@ -123,7 +123,7 @@ user.set("name", "John"); user.set("age", "30"); *!* -// Map iterates as [key, value] pairs, very convenient for destructuring +// Map은 [key, value] 쌍으로 순회하기 때문에 간편히 구조 분해 할당이 가능합니다. for (let [key, value] of user) { */!* alert(`${key}:${value}`); // name:John, then age:30 From 571c0e8d74b8201fb51eff82283d51272f045f2a Mon Sep 17 00:00:00 2001 From: HoonDongKang Date: Sun, 17 May 2026 00:53:30 +0900 Subject: [PATCH 9/9] =?UTF-8?q?[fix]=20=EB=AF=B8=ED=9D=A1=ED=95=9C=20?= =?UTF-8?q?=EB=B2=88=EC=97=AD=20=EC=84=B8=EB=B6=80=20=EC=84=A4=EB=AA=85=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1-js/05-data-types/05-array-methods/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/05-data-types/05-array-methods/article.md b/1-js/05-data-types/05-array-methods/article.md index 0307c3b15..3dfe2c341 100644 --- a/1-js/05-data-types/05-array-methods/article.md +++ b/1-js/05-data-types/05-array-methods/article.md @@ -731,7 +731,7 @@ alert(soldiers[1].age); // 23 `thisArgs`에 `army`를 지정하지 않고 단순히 `users.filter(army.canJoin)`를 사용했다면 `army.canJoin`은 단독 함수처럼 취급되고, 함수 본문 내 `this`는 `undefined`가 되어 에러가 발생했을 겁니다. -`users.filter(army.canJoin, army)`는 `users.filter(user => army.canJoin(user))`로 대체할 수 있습니다. 두 방식은 동일하게 동작하지만, 후자가 좀 더 이해하기 쉬우므로 더 자주 사용됩니다. +`thisArgs`를 사용하는 방식인 `users.filter(army.canJoin, army)`는 `users.filter(user => army.canJoin(user))`로 대체할 수 있습니다. 두 방식은 모두 동일하게 동작하지만, 전자보다 후자가 좀 더 이해하기 쉬우므로 더 자주 사용됩니다. ## 요약