From 56198a437e46f7e9274e350507cbea2d0526532c Mon Sep 17 00:00:00 2001 From: dangen <23185799+dangen-effy@users.noreply.github.com> Date: Wed, 26 Feb 2020 16:23:20 +0900 Subject: [PATCH 01/18] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0bbf554..1f9643c 100644 --- a/README.md +++ b/README.md @@ -347,7 +347,7 @@ aboutMe({ name: '손당근', age: 20 }) // -> 손당근 20 aboutMe({ age: 20, name: '손당근' }) // -> 손당근 20 ... 심지어 매개변수 순서까지 바껴도 잘 출력합니다! aboutMe({ name: '손당근' }) // -> 손당근 비공개 ... 나이를 넘기지 않았으므로 '비공개' 를 출력합니다. -aboutMe({ age: 20 }) // -> 비공개 비공개 +aboutMe({ age: 20 }) // -> 비공개 20 aboutMe({}) // -> 비공개 비공개 ... 둘 다 '비공개' 로 출력 가능합니다! ``` From c60262bd55eb6bb0275241e3ee3ac87e69113977 Mon Sep 17 00:00:00 2001 From: dangen-effy Date: Thu, 27 Feb 2020 00:17:08 +0900 Subject: [PATCH 02/18] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b1d64bc..36a3698 100644 --- a/README.md +++ b/README.md @@ -51,8 +51,6 @@ [Array.prototype.map](#arrayprototypemap) -Array.prototype.reduce - Array.prototype.filter Array.prototype.includes @@ -61,6 +59,8 @@ Array.prototype.every Array.prototype.some +Array.prototype.reduce + String.prototype.split String.prototype.join @@ -537,7 +537,7 @@ if (movie.ironman.ko) { ### 정의 -`map` 은 주어진 배열의 **모든 원소**에 규칙을 적용한 **새로운 배열**을 생성합니다. +`map` 은 주어진 배열의 **모든 원소**에 규칙(`callback`)을 적용한 **새로운 배열**을 생성합니다. ### 특징 (중요🐉) From 12dbed1ab05d3902305eb83da18b3ded4973f1d2 Mon Sep 17 00:00:00 2001 From: dangen-effy Date: Thu, 27 Feb 2020 22:27:39 +0900 Subject: [PATCH 03/18] Add: Spread Syntax, Rest Elements --- README.md | 212 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 144 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index 36a3698..51b5f9c 100644 --- a/README.md +++ b/README.md @@ -39,10 +39,14 @@ ## 모던 자바스크립트가 다루는 개념 -[Rest Parameters](#rest-parameters) +[Spread Syntax](#spread-syntax) [Destructuring Assignment](#destructuring-assignment) +[Rest Parameters](#rest-parameters) + +[Rest Elements](#rest-elements) + [Default Parameter](#default-parameter) [Named Parameter](#named-parameter) @@ -73,61 +77,76 @@ Object.keys --- -# Rest Parameters +# Spread Syntax ### 정의 -Rest Parameters 는 정해지지 않은 수 매개변수를 **실제 배열**로 나타낼 수 있게 합니다. +Spread Syntax 는 특정 객체 혹은 배열의 나머지 요소들을 어떤 객체 혹은 배열 리터럴에 풀어 놓습니다. -## 1. 나머지 매개변수 예시 +### 특징 -👉 시나리오: 개수가 정해지지 않은 매개변수를 입력 받아 이의 총 합을 구하는 함수를 작성하세요. +Spread Syntax 로 새로운 변수가 선언되지 않습니다. + +## 1. 배열 전개구문 + +## 활용 1: 안전한 복사 + +👉 시나리오: `arr1` 과 똑같은 `arr2` 를 만드세요. + +👉 조건: `arr1` 의 변형이 `arr2` 에 영향을 미치지 않게 하세요. ### 불—편 - + ```js -function sum (a, b, ... y, z) { - return a + b + ... + y + z -} // [a-z] 까지 입력받을 수 있습니다. 즉 매개변수의 개수가 정해져 있습니다. 👎 - -console.log(sum(1, 2, 3, 4, 5, 6, 7, 8)) // [i-z] 까지 undefined, 때문에 NaN 출력 👎 +const arr1 = [1, 2, 3] +const arr2 = arr1 // arr2 는 arr1 를 참조합니다. + +arr1.push(4) + +console.log(arr1) // -> [ 1, 2, 3, 4 ] +console.log(arr2) // -> [ 1, 2, 3, 4 ] arr2 까지 변형됐습니다. 👎 ``` ### 편—안 ✅ ```js -function sum (...params) { - return params.reduce((prev, curr) => prev + curr) -} // 매개변수가 몇 개든 합을 잘 구합니다. +const arr1 = [1, 2, 3] +const arr2 = [...arr1] // arr1 를 구조 분해시켜 '새로운' 배열을 만듭니다. 👍 -console.log(sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) // -> 55 👍 +arr1.push(4) + +console.log(arr1) // -> [ 1, 2, 3, 4 ] +console.log(arr2) // -> [ 1, 2, 3 ] 👍 ``` -## 2. 또 다른 나머지 매개변수 예시 +## 2. 객체 전개구문 -👉 시나리오: 첫번째 매개변수와 나머지 매개변수를 곱한 배열을 반환하는 함수를 작성하세요. +## 활용 1: 안전한 객체 얕은 병합 -### 편—안 ✅ +👉 시나리오: 주어진 `obj1` 에 `obj2` 를 병합하세요. + +👉 조건1: 중복 필드가 있다면 `obj2` 의 값으로 덮어씌우세요. + +👉 조건2: 주어진 객체를 변형하지 마세요. + +### 불—편 ```js -function multiply (multiplier, ...params) { - return params.map(param => multiplier * param) -} +const obj1 = { a: 1, b: 1 } +const obj2 = { b: 2, c: 2 } -console.log(multiply(5, 1, 2, 3, 4)) // -> [ 5, 10, 15, 20 ] 👍 +// 나쁘지 않습니다만 obj1 이 수정됩니다. 👎 +const merged = Object.assign(obj1, obj2) ``` -## 3. arguments 와 다른점 - -`arguments` 는 유사 배열입니다. 때문에 `map, reduce, forEach` 와 같은 배열 메소드를 호출 할 수 없습니다. +### 편—안 ✅ ```js -function sum (a, b, c) { - // -> TypeError: arguments.reduce is not a function - return arguments.reduce((prev, curr) => prev + curr) -} +const obj1 = { a: 1, b: 1 } +const obj2 = { b: 2, c: 2 } -sum(1, 2, 3) +// 모든 조건을 만족하며 심플합니다! 👍 +const merged = { ...obj1, ...obj2 } ``` --- @@ -142,7 +161,7 @@ sum(1, 2, 3) 객체를 구조 분해해봅시다. -### 활용 1: 기본값 할당 +## 활용 1: 기본값 할당 👉 시나리오: `me` 객체를 출력하세요. @@ -197,66 +216,123 @@ console.log('자동차', car) 배열을 구조 분해해봅시다. -### 활용 1: 안전한 복사 +--- -👉 시나리오: `arr1` 과 똑같은 `arr2` 를 만드세요. +# Rest Parameters -👉 조건: `arr1` 의 변형이 `arr2` 에 영향을 미치지 않게 하세요. +### 정의 -### 불—편 +Rest Parameters 는 정해지지 않은 수 매개변수를 **실제 배열**로 나타낼 수 있게 합니다. -```js -const arr1 = [1, 2, 3] -const arr2 = arr1 // arr2 는 arr1 를 참조합니다. +## 1. 나머지 매개변수 예시 -arr1.push(4) +👉 시나리오: 개수가 정해지지 않은 매개변수를 입력 받아 이의 총 합을 구하는 함수를 작성하세요. -console.log(arr1) // -> [ 1, 2, 3, 4 ] -console.log(arr2) // -> [ 1, 2, 3, 4 ] arr2 까지 변형됐습니다. 👎 +### 불—편 + +```js +function sum (a, b, ... y, z) { + return a + b + ... + y + z +} // [a-z] 까지 입력받을 수 있습니다. 즉 매개변수의 개수가 정해져 있습니다. 👎 + +console.log(sum(1, 2, 3, 4, 5, 6, 7, 8)) // [i-z] 까지 undefined, 때문에 NaN 출력 👎 ``` ### 편—안 ✅ ```js -const arr1 = [1, 2, 3] -const arr2 = [...arr1] // arr1 를 구조 분해시켜 '새로운' 배열을 만듭니다. 👍 - -arr1.push(4) +function sum (...params) { + return params.reduce((prev, curr) => prev + curr) +} // 매개변수가 몇 개든 합을 잘 구합니다. -console.log(arr1) // -> [ 1, 2, 3, 4 ] -console.log(arr2) // -> [ 1, 2, 3 ] 👍 +console.log(sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) // -> 55 👍 ``` -### 활용 2: 또 다른 안전한 복사 +## 2. 또 다른 나머지 매개변수 예시 -👉 시나리오: 주어진 `fruits` 배열을 이용해 첫번째 과일과 나머지 과일을 출력하세요. +👉 시나리오: 첫번째 매개변수와 나머지 매개변수를 곱한 배열을 반환하는 함수를 작성하세요. -### 불—편 +### 편—안 ✅ ```js -const fruits = ['🍎', '🍌', '🥝'] +function multiply (multiplier, ...params) { + return params.map(param => multiplier * param) +} + +console.log(multiply(5, 1, 2, 3, 4)) // -> [ 5, 10, 15, 20 ] 👍 +``` -// apple 과 rest 는 fruits 를 참조합니다. -const apple = fruits.shift() // fruits 의 첫번째 원소를 제거하고, apple 에 할당 -const rest = fruits +## 3. arguments 와 다른점 -console.log('첫번째 과일', apple) // -> 🍎 -console.log('나머지 과일', ...rest) // -> 🍌 🥝 +`arguments` 는 유사 배열입니다. 때문에 `map, reduce, forEach` 와 같은 배열 메소드를 호출 할 수 없습니다. -console.log(fruits) // -> [ '🍌', '🥝'] fruits 배열이 변형됨 👎 +```js +function sum (a, b, c) { + // -> TypeError: arguments.reduce is not a function + return arguments.reduce((prev, curr) => prev + curr) +} + +sum(1, 2, 3) ``` +--- + + +# Rest Elements + +### 정의 + +Rest Elements 는 객체나 배열의 나머지 요소들을 선언과 동시에 할당합니다. + +### 특징 + +나머지 요소에서 명시한 변수명이 선언되는 효과를 가지며 구조 분해 할당과 함께 사용 시 맨 마지막에 한 번만 위치할 수 있습니다. + +## 활용 1: 배열 나머지 요소 + +👉 시나리오: `arr` 배열의 첫번째 요소를 `first` 에 할당하고 나머지 요소를 `rest` 에 풀어 넣으세요. + ### 편—안 ✅ ```js -const fruits = ['🍎', '🍌', '🥝'] +const arr = [1, 2, 3, 4, 5] +const [first, ...rest] = arr + +console.log(first) // -> 1 +console.log(rest) // -> [ 2, 3, 4, 5 ] 👍 +``` + +## 활용 2: 객체 나머지 요소 + +👉 시나리오: `me` 객체의 `name` 필드만 `name` 에 할당하고 나머지 요소를 `rest` 에 풀어 넣으세요. + +### 불—편 + +```js +const me = { + name: '손당근', + hobby: '산책', + location: 'earth' +} -const [apple, ...rest] = fruits // 배열을 구조 분해시켜 apple 과 rest 가 fruits 를 참조하지 않도록 해줍니다. +// 더 심플하게 안될까요? +const name = me.name +const rest = { + hobby: me.hobby, + location: me.location +} +``` + +### 편—안 ✅ -console.log('첫번째 과일', apple) // -> 🍎 -console.log('나머지 과일', ...rest) // -> 🍌 🥝 +```js +const me = { + name: '손당근', + hobby: '산책', + location: 'earth' +} -console.log(fruits) // -> [ '🍎', '🍌', '🥝' ] fruits 배열 변형 안됨 👍 +const { name, ...rest } = me // 👍 ``` --- @@ -267,7 +343,7 @@ console.log(fruits) // -> [ '🍎', '🍌', '🥝' ] fruits 배열 변형 안됨 Default Parameter 는 매개변수에 기본 값을 할당합니다. -## 1. 매개변수 기본 값 +## 활용1: 매개변수 기본 값 👉 시나리오: 이름 그리고 나이를 출력하는 함수 `aboutMe` 를 작성하세요. @@ -360,7 +436,7 @@ aboutMe({}) // -> 비공개 비공개 ... 둘 다 '비공개' 로 출력 가능 Named Parameter 는 매개변수에 이름을 지정해줍니다. -### 활용1: 선택적 매개변수 +## 활용1: 선택적 매개변수 👉 시나리오: 나이와 직업을 매개변수로 받고 출력하는 함수 `aboutMe` 를 작성하세요. @@ -395,7 +471,7 @@ aboutMe({ age: 20 }) // -> 나이 20 aboutMe({ job: '개발자' }) // -> 직업 개발자 ``` -### 활용2: 순서 없는 매개변수 +## 활용2: 순서 없는 매개변수 매개변수가 3개 이상이면 순서를 잘못 입력할 가능성이 큽니다. @@ -459,7 +535,7 @@ render({ `NaN` -### 활용 1: 배열이 비어있나 확인하기 +## 활용 1: 배열이 비어있나 확인하기 배열은 `length` 프로퍼티를 가지고 있습니다. 이를 검사해 배열이 비어있는지 확인 가능합니다. @@ -483,7 +559,7 @@ if (!arr.length) { // 👍 좋습니다! 0 은 Falsy 기 때문에 배열이 비 } ``` -### 활용 2: 안전히 메소드 호출하기 +## 활용 2: 안전히 메소드 호출하기 존재하지 않는 함수를 호출하면 `TypeError: ... is not a function` 를 `throw` 합니다. @@ -511,7 +587,7 @@ if (iAmNotArray.forEach) { 위에서 언급한 거짓 값을 제외하면 모두 참 값입니다. -### 활용1: 객체 요소 검사 +## 활용1: 객체 요소 검사 `movie` 객체를 참조해 <아이언맨> 이 한글 자막을 지원하는지 확인해 봅시다. From 43b851477dd4cb2c55d2ffa6e9d8bb7b7dab9f91 Mon Sep 17 00:00:00 2001 From: dangen-effy Date: Fri, 28 Feb 2020 09:56:15 +0900 Subject: [PATCH 04/18] Update README.md --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index 51b5f9c..dc88990 100644 --- a/README.md +++ b/README.md @@ -216,6 +216,23 @@ console.log('자동차', car) 배열을 구조 분해해봅시다. +👉 시나리오: 배열 `arr` 의 첫 번째와 세 번째 원소를 각각 `first` 와 `third` 변수에 할당 및 선언하세요. + +### 불—편 + +```js +const arr = [1, 2, 3, 4] +const first = arr[0] // 좀 더 심플하게 안될까요? +const third = arr[2] // 인덱스로 접근하지 않으면서요 +``` + +### 편—안 ✅ + +```js +const arr = [1, 2, 3, 4] +const [first, , third] = arr // 좋습니다. 👍 +``` + --- # Rest Parameters From f10305102aa3d32226b01f4f140d132a30394590 Mon Sep 17 00:00:00 2001 From: dangen-effy Date: Fri, 28 Feb 2020 09:56:51 +0900 Subject: [PATCH 05/18] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index dc88990..1751f50 100644 --- a/README.md +++ b/README.md @@ -222,6 +222,7 @@ console.log('자동차', car) ```js const arr = [1, 2, 3, 4] + const first = arr[0] // 좀 더 심플하게 안될까요? const third = arr[2] // 인덱스로 접근하지 않으면서요 ``` @@ -230,6 +231,7 @@ const third = arr[2] // 인덱스로 접근하지 않으면서요 ```js const arr = [1, 2, 3, 4] + const [first, , third] = arr // 좋습니다. 👍 ``` From e1cf4a00253ba33be777234695742d7634c2828b Mon Sep 17 00:00:00 2001 From: dangen-effy Date: Fri, 28 Feb 2020 09:58:27 +0900 Subject: [PATCH 06/18] Update README.md --- README.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/README.md b/README.md index 1751f50..0396647 100644 --- a/README.md +++ b/README.md @@ -699,12 +699,3 @@ const metropolitanCities = cities.map(city => { return `${city}광역시` }) // console.log(metropolitanCities) // -> [ '부산광역시', '대구광역시', '인천광역시', '광주광역시' ] ``` - -### 좀 더 심플하게 ✅ - -```js -const cities = ['부산', '대구', '인천', '광주'] -const metropolitanCities = cities.map(city => `${city}광역시`) // 👍 - -console.log(metropolitanCities) // -> [ '부산광역시', '대구광역시', '인천광역시', '광주광역시' ] -``` From 0c0ae02b13f75bd159b1a2bce5575bcc0fe5cc96 Mon Sep 17 00:00:00 2001 From: dangen <23185799+dangen-effy@users.noreply.github.com> Date: Sat, 29 Feb 2020 16:38:42 +0900 Subject: [PATCH 07/18] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 0396647..94b1fa0 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ +Buy Me A Coffee 당근밭 심기 + 모던 자바스크립트를 소개합니다. 모던 자바스크립트는 점차 현대적이고 실용적으로 변화하고 있는 ECMAScript 에 적응하는 방법을 알려줍니다. 현재 글을 쓰고 있는 시점인 2020년의 자바스크립트는 이미 풍부한 표준 내장 객체(Standard built-in objects)들을 가지고 있습니다. 덕분에 우리는 더 이상 전통적이고 거대한 라이브러리(lodash 와 같은)들을 사용할 필요성이 줄어들고 있습니다. From b19b923592b62f4f7732485384d4c922ed78dea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=90=ED=83=9C=ED=9D=AC?= Date: Sat, 29 Feb 2020 17:12:46 +0900 Subject: [PATCH 08/18] Update README.md --- README.md | 90 ++----------------------------------------------------- 1 file changed, 2 insertions(+), 88 deletions(-) diff --git a/README.md b/README.md index 0396647..5302610 100644 --- a/README.md +++ b/README.md @@ -53,28 +53,16 @@ [Truthy and Falsy](#truthy-and-falsy) -[Array.prototype.map](#arrayprototypemap) +Promise -Array.prototype.filter +Async Await Array.prototype.includes -Array.prototype.every - -Array.prototype.some - -Array.prototype.reduce - -String.prototype.split - -String.prototype.join - Object.entries Object.values -Object.keys - --- # Spread Syntax @@ -625,77 +613,3 @@ if (movie.ironman.ko) { console.log('한글 자막 개봉') } ``` - ---- - -# Array.prototype.map - -### 정의 - -`map` 은 주어진 배열의 **모든 원소**에 규칙(`callback`)을 적용한 **새로운 배열**을 생성합니다. - -### 특징 (중요🐉) - -`map` 은 주어진 배열을 변형하지 않습니다. - -`map` 은 첫 `callback` 함수가 실행되기 직전에 주어진 배열의 복사본을 생성합니다. 때문에 `callback` 함수를 실행하는 동안에 주어진 배열이 변형되어도 결과에 영향을 미치지 않습니다. - -`map` 은 주어진 배열의 모든 원소에 `callback` 함수를 수행하는 것이 목표입니다. 따라서 중간에 `break or continue` 호출은 불가합니다. - -다시 말해 `map` 은 반복문이 아닙니다. - -`map` 을 탈출하는 방법은 에러를 `throw` 하는 겁니다. 하지만 이 방법을 되도록 사용하지 마세요. `for` 문을 고려하는 게 더 나을지도 모릅니다. - -### 예제 1 - -👉 시나리오: 배열 `numbers` 의 모든 원소에 2 를 곱한 새로운 배열 `result` 를 만드세요. - -### 불—편 - -```js -const numbers = [1, 2, 3, 4, 5] -const result = [] - -// 장황합니다. 👎 -for (let i = 0; i < numbers.length; i++) { - result.push(numbers[i] * 2) -} - -console.log(result) // -> [ 2, 4, 6, 8, 10 ] -``` - -### 편—안 ✅ - -```js -const numbers = [1, 2, 3, 4, 5] -const result = numbers.map(number => { return number * 2 }) - -console.log(result) // -> [ 2, 4, 6, 8, 10 ] -``` - -### 예제 2 - -👉 시나리오: 배열 `cities` 의 모든 원소에 `광역시` 문자열을 뒤에 붙인 새로운 배열 `metropolitanCities` 을 만드세요. - -### 불—편 - -```js -const cities = ['부산', '대구', '인천', '광주'] -const metropolitanCities = [] - -// 장황합니다. 👎 -for (let i = 0; i < cities.length; i++) { - metropolitanCities.push(cities[i] + '광역시') -} - -console.log(metropolitanCities) // -> [ '부산광역시', '대구광역시', '인천광역시', '광주광역시' ] -``` - -### 편—안 ✅ - -```js -const cities = ['부산', '대구', '인천', '광주'] -const metropolitanCities = cities.map(city => { return `${city}광역시` }) // 👍 - -console.log(metropolitanCities) // -> [ '부산광역시', '대구광역시', '인천광역시', '광주광역시' ] -``` From cce9ce43cdc4ccb30bfad75893872294ab982ca4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=86=90=ED=83=9C=ED=9D=AC?= Date: Sat, 29 Feb 2020 20:18:19 +0900 Subject: [PATCH 09/18] Add: Promise --- README.md | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e64fee4..a7f823e 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ -Buy Me A Coffee 당근밭 심기 +Buy Me A Coffee 당근밭 심기 🥕 모던 자바스크립트를 소개합니다. 모던 자바스크립트는 점차 현대적이고 실용적으로 변화하고 있는 ECMAScript 에 적응하는 방법을 알려줍니다. @@ -55,7 +55,7 @@ [Truthy and Falsy](#truthy-and-falsy) -Promise +[Promise](#promise) Async Await @@ -615,3 +615,122 @@ if (movie.ironman.ko) { console.log('한글 자막 개봉') } ``` + +--- + +# Promise + +### 정의 + +Promise 는 **비동기 작업**의 **상태**를 보관하고 추적합니다. + +### 특징 (중요 🐉) + +Promise 는 다음 중 하나의 **상태**를 가집니다. + +- 대기(*pending)*: 이행하거나 거부되지 않은 초기 상태. +- 이행(*fulfilled)*: 연산이 성공적으로 완료됨. +- 거부(*rejected)*: 연산이 실패함. + +[출처: [MDN - Promise](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise)] + +Promise 는 주어진 콜백 함수를 **단 한 번** 실행하며 그 **결과**를 보관합니다. 이러한 특성 때문에 Promise 의 상태는 한 번 결정되면 수정되지 않습니다. + +다시 말해 이미 소비(이행되거나 거부) 된 Promise 는 재사용 할 수 없습니다. + +### 1. 성공 케이스 (fulfilled) + +### 활용 1: 비동기 호출의 상태를 추적하기 + +👉시나리오: 3초 후 주문한 음식이 배달됩니다. 도착 시 이를 출력하세요. + +👉조건1: 배달이 도착하기 전에는 절대로 빨래를 시작하지 마세요. + +### 불—편 + +```js +function delivery () { + setTimeout(() => { console.log('배달 도착') }, 3000) +} + +// 배달을 요청합니다. (비동기 함수 호출) +// 그러나 배달의 현재 상태를 추적하지는 않습니다. +delivery() +console.log('빨래 시작') + +// 결과 👎 +// 빨래 시작 ... 배달이 도착하기도 전에 빨래를 시작했습니다. +// 배달 도착 +``` + + +### 편—안 ✅ + +```js +const delivery = new Promise((resolve) => { + setTimeout(() => { + console.log('배달 도착') + resolve() + }, 3000) +}) + +delivery.then(() => { + console.log('빨래 시작') // 배달이 도착 한 후 빨래를 시작합니다. +}) + +// 결과 👍 +// 배달 도착 +// 빨래 시작 +``` + +### 2. 실패 케이스 (rejected) + +👉시나리오: 3초 후 주문한 음식이 배달됩니다. 그러나 월요일은 휴무입니다. + +👉조건1: 휴무일에는(배달 거부 시) 맥도날드에 방문하세요. + +### 편—안 ✅ + +```js +function delivery (day) { + return new Promise((resolve, reject) => { + if (day === '월요일') { + reject(new Error()) + } + + setTimeout(() => { + resolve() + }, 3000) + }) +} + +delivery('월요일').then(() => { + console.log('음식 받기') +}).catch(() => { + console.log('맥도날드 방문하기') +}) + +// 결과 👍 +// 맥도날드 방문하기 +``` + + +### 3. 일회성 + +Promise 는 비동기 함수의 **결과**를 정확히 보관하고 추적합니다. 또한 한 번 도출된 결과는 변형되지 않습니다. + +👉시나리오: Promise 가 일회성이라는 것을 증명하세요. + +```js +const promise = new Promise((resolve) => { + console.log('안녕') + resolve() +}) + +promise.then() +promise.then() +promise.then() + +// 결과 👍 +// 안녕 ... 단 한 번 출력됨 +``` From 42b79d0445f34c6817c0f273a688b14e33c89764 Mon Sep 17 00:00:00 2001 From: dangen <23185799+dangen-effy@users.noreply.github.com> Date: Sat, 29 Feb 2020 20:21:18 +0900 Subject: [PATCH 10/18] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a7f823e..1193c95 100644 --- a/README.md +++ b/README.md @@ -717,7 +717,7 @@ delivery('월요일').then(() => { ### 3. 일회성 -Promise 는 비동기 함수의 **결과**를 정확히 보관하고 추적합니다. 또한 한 번 도출된 결과는 변형되지 않습니다. +Promise 는 비동기 함수 호출의 결과를 정확히 보관할 의무를 가집니다. 한 번 정해진 결과는 수정되지 않으며 이를 지키기 위해서 주어진 콜백 함수를 단 한 번만 실행합니다. 👉시나리오: Promise 가 일회성이라는 것을 증명하세요. From 2701280b9d47e2df209c16aea847be9ae9a98968 Mon Sep 17 00:00:00 2001 From: dangen <23185799+dangen-effy@users.noreply.github.com> Date: Sat, 29 Feb 2020 23:40:05 +0900 Subject: [PATCH 11/18] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1193c95..a6411f5 100644 --- a/README.md +++ b/README.md @@ -717,7 +717,7 @@ delivery('월요일').then(() => { ### 3. 일회성 -Promise 는 비동기 함수 호출의 결과를 정확히 보관할 의무를 가집니다. 한 번 정해진 결과는 수정되지 않으며 이를 지키기 위해서 주어진 콜백 함수를 단 한 번만 실행합니다. +Promise 는 비동기 함수 호출의 결과를 정확히 보관할 의무를 가집니다. 한 번 정해진 결과는 수정되지 않으며 이를 지키기 위해서 주어진 실행 함수(`executor`)를 단 한 번만 실행합니다. 👉시나리오: Promise 가 일회성이라는 것을 증명하세요. From 0392d70c7d85156fee52378489d28068db0083e3 Mon Sep 17 00:00:00 2001 From: dangen <23185799+dangen-effy@users.noreply.github.com> Date: Sun, 1 Mar 2020 02:41:56 +0900 Subject: [PATCH 12/18] Update README.md --- README.md | 98 ------------------------------------------------------- 1 file changed, 98 deletions(-) diff --git a/README.md b/README.md index a6411f5..3fdeea3 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,6 @@ [Named Parameter](#named-parameter) -[Truthy and Falsy](#truthy-and-falsy) - [Promise](#promise) Async Await @@ -522,102 +520,6 @@ render({ --- -# Truthy and Falsy - -참과 거짓은 Boolean 을 기대하는 문맥에서 `true` `false` 로 평가되는 값입니다. - -## 1. 거짓 값 - -자바스크립트에는 총 7 가지 거짓 값이 존재합니다. - -`false` - -`0` - -`0n` - -`''` - -`null` - -`undefined` - -`NaN` - -## 활용 1: 배열이 비어있나 확인하기 - -배열은 `length` 프로퍼티를 가지고 있습니다. 이를 검사해 배열이 비어있는지 확인 가능합니다. - -### 불—편 - -```js -const arr = [1, 2, 3] - -if (arr.length === 0) { // 좀 더 심플하게 안될까요? - console.log('배열이 비어있음!') -} -``` - -### 편—안 ✅ - -```js -const arr = [1, 2, 3] - -if (!arr.length) { // 👍 좋습니다! 0 은 Falsy 기 때문에 배열이 비어있다면 조건을 만족합니다. - console.log('배열이 비어있음!') -} -``` - -## 활용 2: 안전히 메소드 호출하기 - -존재하지 않는 함수를 호출하면 `TypeError: ... is not a function` 를 `throw` 합니다. - -이를 방지하고자 방어적인 코드를 작성해봅시다. - -### 불—편 - -```js -const notArray = 5000 - -notArray.forEach(it => console.log(it)) // -> TypeError: notArray.forEach is not a function -``` - -### 편—안 ✅ - -```js -const iAmNotArray = 5000 - -if (iAmNotArray.forEach) { - iAmNotArray.forEach(it => console.log(it)) // 👍 -} -``` - -## 2. 참 값 - -위에서 언급한 거짓 값을 제외하면 모두 참 값입니다. - -## 활용1: 객체 요소 검사 - -`movie` 객체를 참조해 <아이언맨> 이 한글 자막을 지원하는지 확인해 봅시다. - -### 편—안 ✅ - -```js -const movie = { - ironman: { - ko: '아이언맨 4', - en: 'Iron Man 4' - } -} - -// 좋습니다. 👍 -if (movie.ironman.ko) { - console.log('한글 자막 개봉') -} -``` - ---- - # Promise ### 정의 From 089b9b39fc6086d19d4c3d5e4e8ed6febdee7f6b Mon Sep 17 00:00:00 2001 From: dangen <23185799+dangen-effy@users.noreply.github.com> Date: Mon, 2 Mar 2020 22:37:54 +0900 Subject: [PATCH 13/18] Update README.md --- README.md | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 3fdeea3..12fb76c 100644 --- a/README.md +++ b/README.md @@ -569,20 +569,23 @@ console.log('빨래 시작') ### 편—안 ✅ ```js -const delivery = new Promise((resolve) => { - setTimeout(() => { - console.log('배달 도착') - resolve() - }, 3000) -}) +function delivery () { + return new Promise((resolve) => { + setTimeout(() => { + console.log('배달 도착') + resolve() + }, 3000) + }) +} -delivery.then(() => { +delivery().then(() => { console.log('빨래 시작') // 배달이 도착 한 후 빨래를 시작합니다. }) // 결과 👍 // 배달 도착 // 빨래 시작 + ``` ### 2. 실패 케이스 (rejected) @@ -624,6 +627,7 @@ Promise 는 비동기 함수 호출의 결과를 정확히 보관할 의무를 👉시나리오: Promise 가 일회성이라는 것을 증명하세요. ```js +// new Promise 를 한순간 이미 프로미스 소진 const promise = new Promise((resolve) => { console.log('안녕') resolve() @@ -635,4 +639,5 @@ promise.then() // 결과 👍 // 안녕 ... 단 한 번 출력됨 + ``` From 0a3a7f3bdba03fc3de7fc2f3366a6916cc89d57c Mon Sep 17 00:00:00 2001 From: dangen-effy Date: Tue, 3 Mar 2020 22:21:10 +0900 Subject: [PATCH 14/18] Add: Async Function --- README.md | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 113 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 12fb76c..51008b4 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ [Promise](#promise) -Async Await +[Async Function](#async-function) Array.prototype.includes @@ -561,8 +561,8 @@ delivery() console.log('빨래 시작') // 결과 👎 -// 빨래 시작 ... 배달이 도착하기도 전에 빨래를 시작했습니다. -// 배달 도착 +// -> 빨래 시작 ... 배달이 도착하기도 전에 빨래를 시작했습니다. +// -> 배달 도착 ``` @@ -583,8 +583,8 @@ delivery().then(() => { }) // 결과 👍 -// 배달 도착 -// 빨래 시작 +// -> 배달 도착 +// -> 빨래 시작 ``` @@ -616,7 +616,7 @@ delivery('월요일').then(() => { }) // 결과 👍 -// 맥도날드 방문하기 +// -> 맥도날드 방문하기 ``` @@ -638,6 +638,112 @@ promise.then() promise.then() // 결과 👍 -// 안녕 ... 단 한 번 출력됨 +// -> 안녕 ... 단 한 번 출력됨 +``` + +--- + +# Async Function + +### 정의 + +Promise 객체를 반환하는 함수 + +### 특징 + +Async Function 은 `await` 키워드를 사용 가능케 해줍니다. `await` 키워드는 Async Function 에서만 유효합니다. + +`await` 키워드는 Async Function 이 끝나길(`return or throw`) 기다립니다. + +Async Function 는 `return` 혹은 `throw` 문으로 끝낼 수 있습니다. + +Async/Await 을 사용하면 일련의 비동기 작업을 비교적 쉽게 동기 방식으로 호출 가능케 해줍니다. + +### 참고 + +예시 코드들은 간결한 코드를 보여주기 위해 `top-level-await` 기능이 탑재된 환경에서 진행했습니다. `top-level-await` 은 ECMAScript proposal stage 3 상태며 자세한 내용은 아래 링크를 참고해 주세요. + +[tc39/proposal-top-level-await - GitHub](https://github.com/tc39/proposal-top-level-await) + +### 1. 비동기 작업하기 + +👉시나리오: 구글 검색 페이지를 크롤링 해오세요. 크롤링을 완료하는 것을 기다리지 말고 `이메일을 전송` 하세요. + +👉조건: Async Function 을 활용하세요. + +### 편—안 ✅ + +```js +async function google () { + // ... + console.log('구글 크롤링 완료') +} + +google() // 비동기적으로 실행됩니다. +console.log('이메일 전송') + +// 결과 👍 +// -> 이메일 전송 +// -> 구글 크롤링 완료 +``` + +### 2. 비동기 작업을 기다리기 +👉시나리오: 구글 검색 페이지를 크롤링 해오세요. 크롤링을 완료한 뒤 `이메일을 전송` 하세요. + +👉조건: Async Function 을 활용하세요. + +### 편—안 ✅ +```js +async function google () { + // ... + console.log('구글 크롤링 완료') +} + +await google() // await 키워드가 동기적으로 실행하도록 만들어줍니다. 👍 +console.log('이메일 전송') + +// 결과 👍 +// -> 구글 크롤링 완료 +// -> 이메일 전송 +``` +### 3. 결과 다루기 + +### 활용 1: 성공 (return) + +👉시나리오: `getUser` 함수로 사용자 정보를 가져오세요. 결과를 받아 `name` 필드의 값을 출력하세요. + +👉조건: `await` 키워드로 `getUser` 함수가 반환하는 값을 받아오세요. + +### 편—안 ✅ + +```js +async function getUser () { + const result = await dbQuery() + return result +} + +const user = await getUser() // await 키워드가 getUser 함수의 반환을 기다립니다. 👍 + +console.log(user.name) +``` + +### 활용2: 실패 (throw) + +👉시나리오: 배달 음식을 주문하세요. 배달이 도착하면(`return`) 음식을 먹고, 만약 주문이 취소되면(`throw`) 방문 포장을 해오세요. + +### 편—안 ✅ + +```js +async function delivery () { + // ... + throw new Error('주문 거절!') +} + +try { + await delivery() // await 키워드가 덕분에 비동기 호출의 실패를 다룰수 있습니다. 👍 + // ... 배달 음식 먹기 +} catch (error) { + // ... 방문 포장 해오기 +} ``` From e8e2e4be4e14a55d38e3fec22dcc5f694c285239 Mon Sep 17 00:00:00 2001 From: dangen <23185799+dangen-effy@users.noreply.github.com> Date: Tue, 3 Mar 2020 22:22:43 +0900 Subject: [PATCH 15/18] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 51008b4..2b8bee3 100644 --- a/README.md +++ b/README.md @@ -737,7 +737,7 @@ console.log(user.name) ```js async function delivery () { // ... - throw new Error('주문 거절!') + throw new Error('주문 !') } try { From f936f255de9d53be03b351e015a4ff5c8e431850 Mon Sep 17 00:00:00 2001 From: dangen-effy Date: Wed, 4 Mar 2020 00:47:19 +0900 Subject: [PATCH 16/18] Update README.md --- README.md | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2b8bee3..f4eec20 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,10 @@ ## 모던 자바스크립트가 다루는 개념 +[Let Declaration](#let-declaration) + +Const Declaration + [Spread Syntax](#spread-syntax) [Destructuring Assignment](#destructuring-assignment) @@ -57,11 +61,63 @@ [Async Function](#async-function) -Array.prototype.includes +--- + +# Let Declaration + +### 정의 + +블록 레벨 유효 범위를 갖는 지역 변수를 선언합니다. + +### 특징 + +`let` 으로 선언한 변수는 재선언할 수 없습니다. + +`let` 으로 선언한 변수는 값을 재할당 할 수 있습니다. + +`let` 은 블록 레벨 유효 범위를 가집니다. 블록 레벨은 모든 코드 블록을 의미합니다. 예를 들어 `함수`, `if`, `switch`, `for`, `while`, `try-catch`, ... 내부에서 선언된 `let` 변수는 외부에서 접근할 수 없습니다. + +### 참고 + +`let` 으로 선언된 변수들은 코드를 읽을 때 변함(`mutable`)을 기대하게 만듭니다. 이는 코드 리뷰어가 해당 변수가 언제 바뀌는지 계속해서 추적하게 만듭니다. 이는 굉장히 피곤한 일입니다. 따라서 변하지 않는 변수들은 **언제나** 상수(`const`)로 선언하세요. + +### 1. 재선언 불가능 -Object.entries +👉시나리오: `let` 이 `var` 과 다르게 재선언 할 수 없다는 걸 증명하세요. -Object.values +```js +var a +var a // 재선언 통과 + +let b +let b // -> SyntaxError: Identifier 'b' has already been declared 👍 +``` + +### 2. 재할당 + +👉시나리오: `let` 이 `const` 와 다르게 재할당 가능한 걸 증명하세요. + +```js +let a = 1 +a = 2 // 재할당 가능 👍 + +const b = 1 +b = 2 // -> TypeError: Assignment to constant variable. +``` + +### 3. 유효 범위 + +👉시나리오: `let` 이 `var` 과 다르게 블록 유효 범위를 가지는걸 증명하세요. + +```js +if (true) { + var a = 1 + let b = 1 +} + +console.log(a) // -> 1 +console.log(b) // -> ReferenceError: b is not defined 👍 +``` --- @@ -737,7 +793,7 @@ console.log(user.name) ```js async function delivery () { // ... - throw new Error('주문 !') + throw new Error('주문 취소!') } try { From ac0377c558235adda87aed0999d95872b1e3e961 Mon Sep 17 00:00:00 2001 From: dangen <23185799+dangen-effy@users.noreply.github.com> Date: Wed, 4 Mar 2020 12:05:22 +0900 Subject: [PATCH 17/18] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index f4eec20..010643b 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,6 @@ -Buy Me A Coffee 당근밭 심기 🥕 - 모던 자바스크립트를 소개합니다. 모던 자바스크립트는 점차 현대적이고 실용적으로 변화하고 있는 ECMAScript 에 적응하는 방법을 알려줍니다. 현재 글을 쓰고 있는 시점인 2020년의 자바스크립트는 이미 풍부한 표준 내장 객체(Standard built-in objects)들을 가지고 있습니다. 덕분에 우리는 더 이상 전통적이고 거대한 라이브러리(lodash 와 같은)들을 사용할 필요성이 줄어들고 있습니다. From 7f9c2e6becdd1be9c59d70f8b8f53bbb242b6ff8 Mon Sep 17 00:00:00 2001 From: dangen-effy Date: Wed, 4 Mar 2020 23:33:44 +0900 Subject: [PATCH 18/18] Update README.md --- README.md | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 010643b..c392ae7 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ [Let Declaration](#let-declaration) -Const Declaration +[Const Declaration](#const-declaration) [Spread Syntax](#spread-syntax) @@ -119,6 +119,54 @@ console.log(b) // -> ReferenceError: b is not defined 👍 --- +# Const Declaration + +### 정의 + +블록 레벨 유효 범위를 갖는 **상수**를 선언합니다. + +### 특징 + +`const` 는 선언과 동시에 할당해야 합니다. 즉 언제나 초깃값을 필요로 합니다. + +`const` 는 재할당 할 수 없습니다. + +`const` 는 `let` 과 동일하게 블록 레벨 유효 범위를 가집니다. + +### 1. 선언과 동시에 할당 + +👉시나리오: `const` 가 선언과 동시에 할당해야 함을 증명하세요. + +```js +const a = 1 +const b // -> SyntaxError: Missing initializer in const declaration +``` + +### 2. 재할당 불가능 + +👉시나리오: `const` 가 재할당 불가능함을 증명하세요. + +```js +const a = 1 +a = 2 // -> TypeError: Assignment to constant variable +``` + +### 3. 유효 범위 + +👉시나리오: `const` 가 `let` 과 동일하게 블록 레벨 유효 범위를 가지는 것을 증명하세요. + +```js +if (true) { + var a = 1 + const b = 1 +} + +console.log(a) // -> 1 +console.log(b) // -> ReferenceError: b is not defined 👍 +``` + +--- + # Spread Syntax ### 정의