├── .gitignore ├── CONCLUSION.md ├── README.md ├── SUMMARY.md ├── async ├── 01-promise.md ├── 02-async-await.md └── README.md ├── basics ├── 01-hello-javascript.md ├── 02-variables.md ├── 03-operator.md ├── 04-conditions.md ├── 05-function.md ├── 06-object.md ├── 07-array.md ├── 08-loop.md ├── 09-array-functions.md ├── 10-prototype-class.md └── README.md ├── book.json ├── gitbook-plugin-comment ├── index.js └── package.json ├── html ├── 01-counter.md ├── 02-modal.md └── README.md ├── package.json ├── reference.md ├── useful ├── 01-ternary.md ├── 02-truthy-and-falsy.md ├── 03-short-circuiting.md ├── 04-default-function-params.md ├── 05-smarter-conditions.md ├── 06-destructuring.md ├── 07-spread-and-rest.md ├── 08-scope.md └── README.md └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | _book 2 | .vscode 3 | node_modules -------------------------------------------------------------------------------- /CONCLUSION.md: -------------------------------------------------------------------------------- 1 | # 맺으면서 2 | 3 | 이 튜토리얼을 통해 JavaScript 기초를 배우고, 유용한 문법들도 배웠습니다. 그리고, HTML 을 JavaScript 와 연동해야 할 때 어떻게 해야 하는지에 대한 기본적인 방법도 배웟지요. 이제, 여러분들은 React, Vue, Angular 등의 라이브러리/프레임워크를 사용한 프런트엔드 개발 혹은 Node.js 를 통한 백엔드 개발을 시작해보시면 됩니다! 4 | 5 | 물론, 이 튜토리얼에서 커버하지 못한 내용도 있습니다. 하지만, 이 정도 배워놓고 나서 다른걸 공부하면서, 공부하는 과정에서 잘 모르는것은 검색해가면서 진행하면 충분 할 것입니다. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 벨로퍼트와 함께하는 모던 자바스크립트 2 | 3 | > 본 강의 자료는 [패스트캠퍼스 온라인 강의](https://www.fastcampus.co.kr/dev_online_react/)에서 제공하는 JavaScript 강의에서 사용되는 강의 문서입니다. 4 | 5 | ## 강의 소개 6 | 7 | 이 강의에서 뜻하는 "모던 자바스크립트"는, 2019년에 사용하기에 걸맞는 그리고 또 뒤쳐지지 않는, 그런 자바스크립트를 칭합니다. 이 강의에서는 자바스크립트 기초부터 시작해서 실무에서 필요한 핵심 지식들까지 다뤄보게 됩니다. 8 | 9 | ## 강의 대상 10 | 11 | 이 강의는 프로그래밍을 한번도 해본적 없는 사람이 들어도 도움이 될 수 있으며, 자바스크립트 기초를 이미 배우신 분들도 도움이 될 수 있습니다. 특히 React, Angular, Vue 등의 웹 프레임워크 및 라이브러리를 공부하기 전에 이 튜토리얼을 통하여 자바스크립트를 한번 공부하고 나면 큰 도움이 될 수 있습니다. 그리고, Node.js 를 통하여 백엔드 개발을 하기 전에도 도움이 될 수 있습니다. 12 | 13 | > 자바스크립트를 이미 아신다면 강의 초반부는 살짝 지루 할 수도 있습니다. 알고 있는 내용은 스킵을 하면서 보셔도 무방합니다 :) 14 | 15 | ## 튜토리얼을 진행하기전에 필요한 것 16 | 17 | 튜토리얼을 진행하기전에 꼭 필요한 것은 바로, 개발 공부에 대한 관심입니다. 그리고, 왜 개발을 배워야 하는지에 대한 동기입니다. 단순히 "프로그래밍을 배우고싶다" 또는 "나도 프로그래머가 되고 싶다"라는 생각은 개발 공부를 할 때 있어서 작심삼일이 되기 쉬운 마인드입니다. 18 | 19 | 그 대신에, 나는 "프로그래밍을 배워서 어떤 프로젝트를 만들어보고 싶다" 와 같은 확실한 목표를 세우고 개발 공부를 진행하시기를 바랍니다. 그 어떠한 목표가 거창한것이 아니여도 좋습니다. 진짜 간단한 프로젝트라 하더라도, 만들고 싶은 것을 목표로 삼고 개발 공부를 해보세요. 20 | 21 | 추가적으로, 개발 공부를 하게 될 때 있어서 필요한 도구들은 앞으로 하나하나 설치 할 것입니다. 22 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | - [벨로퍼트와 함께하는 모던 자바스크립트](README.md) 4 | - [1장. 자바스크립트 입문](./basics/README.md) 5 | - [01. Hello JavaScript](./basics/01-hello-javascript.md) 6 | - [02. 변수](./basics/02-variables.md) 7 | - [03. 연산자](./basics/03-operator.md) 8 | - [04. 조건문](./basics/04-conditions.md) 9 | - [05. 함수](./basics/05-function.md) 10 | - [06. 객체](./basics/06-object.md) 11 | - [07. 배열](./basics/07-array.md) 12 | - [08. 반복문](./basics/08-loop.md) 13 | - [09. 배열 내장함수](./basics/09-array-functions.md) 14 | - [10. 프로토타입과 클래스](./basics/10-prototype-class.md) 15 | - [2장. 알고있으면 유용한 자바스크립트 문법](./useful/README.md) 16 | - [01. 삼항 연산자](./useful/01-ternary.md) 17 | - [02. Truthy and Falsy](./useful/02-truthy-and-falsy.md) 18 | - [03. 단축 평가 논리 계산법](./useful/03-short-circuiting.md) 19 | - [04. 함수의 기본 파라미터](./useful/04-default-function-params.md) 20 | - [05. 조건문 더 스마트하게 쓰기](./useful/05-smarter-conditions.md) 21 | - [06. 비구조화 할당 (구조 분해) 문법](./useful/06-destructuring.md) 22 | - [07. spread 와 rest 문법](./useful/07-spread-and-rest.md) 23 | - [08. scope 의 이해](./useful/08-scope.md) 24 | - [3장. 자바스크립트에서 비동기 처리 다루기](./async/README.md) 25 | - [01. Promise](./async/01-promise.md) 26 | - [02. async/await](./async/02-async-await.md) 27 | - [4장. HTML 과 JavaScript 연동하기](./html/README.md) 28 | - [01. 카운터](./html/01-counter.md) 29 | - [02. 모달](./html/02-modal.md) 30 | - [맺으면서](./CONCLUSION.md) 31 | - [참고 문헌](./reference.md) -------------------------------------------------------------------------------- /async/01-promise.md: -------------------------------------------------------------------------------- 1 | ## 01. Promise 2 | 3 | 프로미스는 비동기 작업을 조금 더 편하게 처리 할 수 있도록 ES6 에 도입된 기능입니다. 이전에는 비동기 작업을 처리 할 때에는 콜백 함수로 처리를 해야 했었는데요, 콜백 함수로 처리를 하게 된다면 비동기 작업이 많아질 경우 코드가 쉽게 난잡해지게 되었습니다. 4 | 5 | 한번 숫자 n 을 파라미터로 받아와서 다섯번에 걸쳐 1초마다 1씩 더해서 출력하는 작업을 setTimeout 으로 구현해봅시다. 6 | 7 | ```javascript 8 | function increaseAndPrint(n, callback) { 9 | setTimeout(() => { 10 | const increased = n + 1; 11 | console.log(increased); 12 | if (callback) { 13 | callback(increased); 14 | } 15 | }, 1000); 16 | } 17 | 18 | increaseAndPrint(0, n => { 19 | increaseAndPrint(n, n => { 20 | increaseAndPrint(n, n => { 21 | increaseAndPrint(n, n => { 22 | increaseAndPrint(n, n => { 23 | console.log('끝!'); 24 | }); 25 | }); 26 | }); 27 | }); 28 | }); 29 | ``` 30 | 31 | 코드 읽기가 복잡하죠? 이런 식의 코드를 Callback Hell (콜백지옥) 이라고 부릅니다. 32 | 33 |  34 | 35 | 비동기적으로 처리해야 하는 일이 많아질수록, 코드의 깊이가 계속 깊어지는 현상이 있는데요, Promise 를 사용하면 이렇게 코드의 깊이가 깊어지는 현상을 방지 할 수 있습니다. 36 | 37 | ### Promise 만들기 38 | 39 | Promise 는 다음과 같이 만듭니다. 40 | 41 | ```javascript 42 | const myPromise = new Promise((resolve, reject) => { 43 | // 구현.. 44 | }) 45 | ``` 46 | 47 | Promise 는 성공 할 수도 있고, 실패 할 수도 있습니다. 성공 할 때에는 resolve 를 호출해주면 되고, 실패할 때에는 reject 를 호출해주면 됩니다. 지금 당장은 실패하는 상황은 고려하지 않고, 1초 뒤에 성공시키는 상황에 대해서만 구현을 해보겠습니다. 48 | 49 | ```javascript 50 | const myPromise = new Promise((resolve, reject) => { 51 | setTimeout(() => { 52 | resolve(1); 53 | }, 1000); 54 | }); 55 | 56 | myPromise.then(n => { 57 | console.log(n); 58 | }); 59 | ``` 60 | 61 | resolve 를 호출 할 때 특정 값을 파라미터로 넣어주면, 이 값을 작업이 끝나고 나서 사용 할 수 있습니다. 작업이 끝나고 나서 또 다른 작업을 해야 할 때에는 Promise 뒤에 `.then(...)` 을 붙여서 사용하면 됩니다. 62 | 63 | 이번에는, 1초뒤에 실패되게끔 해봅시다. 64 | 65 | 66 | ```javascript 67 | const myPromise = new Promise((resolve, reject) => { 68 | setTimeout(() => { 69 | reject(new Error()); 70 | }, 1000); 71 | }); 72 | 73 | myPromise 74 | .then(n => { 75 | console.log(n); 76 | }) 77 | .catch(error => { 78 | console.log(error); 79 | }); 80 | ``` 81 | 82 | 실패하는 상황에서는 `reject` 를 사용하고, `.catch` 를 통하여 실패했을시 수행 할 작업을 설정 할 수 있습니다. 83 | 84 | 85 | 86 | 이제, Promise 를 만드는 함수를 작성해봅시다. 87 | 88 | ```javascript 89 | function increaseAndPrint(n) { 90 | return new Promise((resolve, reject) => { 91 | setTimeout(() => { 92 | const value = n + 1; 93 | if (value === 5) { 94 | const error = new Error(); 95 | error.name = 'ValueIsFiveError'; 96 | reject(error); 97 | return; 98 | } 99 | console.log(value); 100 | resolve(value); 101 | }, 1000); 102 | }); 103 | } 104 | 105 | increaseAndPrint(0).then((n) => { 106 | console.log('result: ', n); 107 | }) 108 | ``` 109 | 110 |  111 | 112 | 여기까지만 보면, 결국 함수를 전달하는건데, 뭐가 다르지 싶을수도 있습니다. 하지만, Promise 의 속성 중에는, 만약 then 내부에 넣은 함수에서 또 Promise 를 리턴하게 된다면, 연달아서 사용 할 수 있습니다. 다음과 같이 말이죠. 113 | 114 | ```javascript 115 | function increaseAndPrint(n) { 116 | return new Promise((resolve, reject) => { 117 | setTimeout(() => { 118 | const value = n + 1; 119 | if (value === 5) { 120 | const error = new Error(); 121 | error.name = 'ValueIsFiveError'; 122 | reject(error); 123 | return; 124 | } 125 | console.log(value); 126 | resolve(value); 127 | }, 1000); 128 | }); 129 | } 130 | 131 | increaseAndPrint(0) 132 | .then(n => { 133 | return increaseAndPrint(n); 134 | }) 135 | .then(n => { 136 | return increaseAndPrint(n); 137 | }) 138 | .then(n => { 139 | return increaseAndPrint(n); 140 | }) 141 | .then(n => { 142 | return increaseAndPrint(n); 143 | }) 144 | .then(n => { 145 | return increaseAndPrint(n); 146 | }) 147 | .catch(e => { 148 | console.error(e); 149 | }); 150 | ``` 151 | 152 |  153 | 154 | 위 코드는 이렇게 정리를 할 수 있습니다. 155 | 156 | ```javascript 157 | function increaseAndPrint(n) { 158 | return new Promise((resolve, reject) => { 159 | setTimeout(() => { 160 | const value = n + 1; 161 | if (value === 5) { 162 | const error = new Error(); 163 | error.name = 'ValueIsFiveError'; 164 | reject(error); 165 | return; 166 | } 167 | console.log(value); 168 | resolve(value); 169 | }, 1000); 170 | }); 171 | } 172 | 173 | increaseAndPrint(0) 174 | .then(increaseAndPrint) 175 | .then(increaseAndPrint) 176 | .then(increaseAndPrint) 177 | .then(increaseAndPrint) 178 | .then(increaseAndPrint) 179 | .catch(e => { 180 | console.error(e); 181 | }); 182 | ``` 183 | 184 | Promise 를 사용하면, 비동기 작업의 개수가 많아져도 코드의 깊이가 깊어지지 않게 됩니다. 185 | 186 | 하지만, 이것도 불편한점이 있긴 합니다. 에러를 잡을 때 몇번째에서 발생했는지 알아내기도 어렵고 특정 조건에 따라 분기를 나누는 작업도 어렵고, 특정 값을 공유해가면서 작업을 처리하기도 까다롭습니다. 다음 섹션에서 배울 async/await 을 사용하면, 이러한 문제점을 깔끔하게 해결 할 수 있습니다. -------------------------------------------------------------------------------- /async/02-async-await.md: -------------------------------------------------------------------------------- 1 | ## 02. async/await 2 | 3 | async/await 문법은 ES8에 해당하는 문법으로서, Promise 를 더욱 쉽게 사용 할 수 있게 해줍니다. 4 | 5 | 기본적인 사용법을 알아봅시다. 6 | 7 | ```javascript 8 | function sleep(ms) { 9 | return new Promise(resolve => setTimeout(resolve, ms)); 10 | } 11 | 12 | async function process() { 13 | console.log('안녕하세요!'); 14 | await sleep(1000); // 1초쉬고 15 | console.log('반갑습니다!'); 16 | } 17 | 18 | process(); 19 | ``` 20 | 21 | async/await 문법을 사용할 때에는, 함수를 선언 할 때 함수의 앞부분에 `async` 키워드를 붙여주세요. 그리고 Promise 의 앞부분에 `await` 을 넣어주면 해당 프로미스가 끝날때까지 기다렸다가 다음 작업을 수행 할 수 있습니다. 22 | 23 | 위 코드에서는 `sleep` 이라는 함수를 만들어서 파라미터로 넣어준 시간 만큼 기다리는 Promise 를 만들고, 이를 `process` 함수에서 사용해주었습니다. 24 | 25 | 함수에서 `async` 를 사용하면, 해당 함수는 결과값으로 Promise 를 반환하게 됩니다. 따라서 다음과 같이 코드를 작성 할 수 있습니다. 26 | 27 | ```javascript 28 | function sleep(ms) { 29 | return new Promise(resolve => setTimeout(resolve, ms)); 30 | } 31 | 32 | async function process() { 33 | console.log('안녕하세요!'); 34 | await sleep(1000); // 1초쉬고 35 | console.log('반갑습니다!'); 36 | } 37 | 38 | process().then(() => { 39 | console.log('작업이 끝났어요!'); 40 | }); 41 | ``` 42 | 43 | `async` 함수에서 에러를 발생 시킬때에는 `throw` 를 사용하고, 에러를 잡아낼 때에는 try/catch 문을 사용합니다. 44 | 45 | ```javascript 46 | function sleep(ms) { 47 | return new Promise(resolve => setTimeout(resolve, ms)); 48 | } 49 | 50 | async function makeError() { 51 | await sleep(1000); 52 | const error = new Error(); 53 | throw error; 54 | } 55 | 56 | async function process() { 57 | try { 58 | await makeError(); 59 | } catch (e) { 60 | console.error(e); 61 | } 62 | } 63 | 64 | process(); 65 | ``` 66 | 67 |  68 | 69 | 70 | 이번에는, 비동기 함수를 몇개 더 만들어보겠습니다. 71 | 72 | ```javascript 73 | function sleep(ms) { 74 | return new Promise(resolve => setTimeout(resolve, ms)); 75 | } 76 | 77 | const getDog = async () => { 78 | await sleep(1000); 79 | return '멍멍이'; 80 | }; 81 | 82 | const getRabbit = async () => { 83 | await sleep(500); 84 | return '토끼'; 85 | }; 86 | const getTurtle = async () => { 87 | await sleep(3000); 88 | return '거북이'; 89 | }; 90 | 91 | async function process() { 92 | const dog = await getDog(); 93 | console.log(dog); 94 | const rabbit = await getRabbit(); 95 | console.log(rabbit); 96 | const turtle = await getTurtle(); 97 | console.log(turtle); 98 | } 99 | 100 | process(); 101 | 102 | ``` 103 | 104 | 현재 위 코드에서는 `getDog` 는 1초, `getRabbit` 은 0.5초, `getTurtle` 은 3초가 걸리고 있습니다. 이 함수들을 `process` 함수에서 연달아서 사용하게 되면서, `process` 함수가 실행되는 총 시간은 4.5초가 됩니다. 105 | 106 | 지금은 `getDog` -> `getRabbit` -> `getTurtle` 순서대로 실행이 되고 있는데요, 하나가 끝나야 다음 작업이 시작하고 있는데, 동시에 작업을 시작하고 싶다면, 다음과 같이 `Promise.all` 을 사용해야합니다. 107 | 108 | ```javascript 109 | function sleep(ms) { 110 | return new Promise(resolve => setTimeout(resolve, ms)); 111 | } 112 | 113 | const getDog = async () => { 114 | await sleep(1000); 115 | return '멍멍이'; 116 | }; 117 | 118 | const getRabbit = async () => { 119 | await sleep(500); 120 | return '토끼'; 121 | }; 122 | const getTurtle = async () => { 123 | await sleep(3000); 124 | return '거북이'; 125 | }; 126 | 127 | async function process() { 128 | const results = await Promise.all([getDog(), getRabbit(), getTurtle()]); 129 | console.log(results); 130 | } 131 | 132 | process(); 133 | ``` 134 | 135 |  136 | 137 | 만약에 여기서 배열 비구조화 할당 문법을 사용한다면 각 결과값을 따로 따로 추출해서 조회 할 수 있습니다. 138 | 139 | ```javascript 140 | function sleep(ms) { 141 | return new Promise(resolve => setTimeout(resolve, ms)); 142 | } 143 | 144 | const getDog = async () => { 145 | await sleep(1000); 146 | return '멍멍이'; 147 | }; 148 | 149 | const getRabbit = async () => { 150 | await sleep(500); 151 | return '토끼'; 152 | }; 153 | const getTurtle = async () => { 154 | await sleep(3000); 155 | return '거북이'; 156 | }; 157 | 158 | async function process() { 159 | const [dog, rabbit, turtle] = await Promise.all([ 160 | getDog(), 161 | getRabbit(), 162 | getTurtle() 163 | ]); 164 | console.log(dog); 165 | console.log(rabbit); 166 | console.log(turtle); 167 | } 168 | 169 | process(); 170 | ``` 171 | 172 | 173 | `Promise.all` 를 사용 할 때에는, 등록한 프로미스 중 하나라도 실패하면, 모든게 실패 한 것으로 간주합니다. 174 | 175 | 176 | 이번에는 `Promise.race` 라는 것에 대해서 알아봅시다. 이 함수는 `Promise.all` 과 달리, 여러개의 프로미스를 등록해서 실행했을 때 가장 빨리 끝난것 하나만의 결과값을 가져옵니다. 177 | 178 | ```javascript 179 | function sleep(ms) { 180 | return new Promise(resolve => setTimeout(resolve, ms)); 181 | } 182 | 183 | const getDog = async () => { 184 | await sleep(1000); 185 | return '멍멍이'; 186 | }; 187 | 188 | const getRabbit = async () => { 189 | await sleep(500); 190 | return '토끼'; 191 | }; 192 | const getTurtle = async () => { 193 | await sleep(3000); 194 | return '거북이'; 195 | }; 196 | 197 | async function process() { 198 | const first = await Promise.race([ 199 | getDog(), 200 | getRabbit(), 201 | getTurtle() 202 | ]); 203 | console.log(first); 204 | } 205 | 206 | process(); 207 | ``` 208 | 209 | `Promise.race` 의 경우엔 가장 다른 Promise 가 먼저 성공하기 전에 가장 먼저 끝난 Promise 가 실패하면 이를 실패로 간주합니다. 따라서, 현재 위의 코드에서 `getRabbit` 에서 에러를 발생시킨다면 에러를 잡아낼 수 있지만, `getTurtle` 이나 `getDog` 에서 발생한 에러는 무시됩니다. -------------------------------------------------------------------------------- /async/README.md: -------------------------------------------------------------------------------- 1 | # 3장. 자바스크립트에서 비동기 처리 다루기 2 | 3 | 자바스크립트의 동기적 처리와 비동기 처리에 대해서 알아봅시다. 4 | 5 |  6 | 7 | 만약 작업을 동기적으로 처리한다면 작업이 끝날 때까지 기다리는 동안 중지 상태가 되기 때문에 다른 작업을 할 수 없습니다. 그리고 작업이 끝나야 비로소 그 다음 예정된 작업을 할 수 있죠. 하지만 이를 비동기적으로 처리를 한다면 흐름이 멈추지 않기 때문에 동시에 여러 가지 작업을 처리할 수도 있고, 기다리는 과정에서 다른 함수도 호출할 수 있습니다. 8 | 9 | 그러면, 한번 코드를 보고 이해해봅시다. 10 | 11 | 연산량이 많은 작업을 처리하는 함수를 만들어보겠습니다. 12 | 13 | 우선, Codesandbox 의 설정에서 sandbox.config.json 을 열어서 Infinite Loop Protection 이라는 속성을 비활성화하세요. 14 | 15 |  16 | 17 | 그 다음에, index.js 를 다음과 같이 수정해보세요. 18 | 19 | ```javascript 20 | function work() { 21 | const start = Date.now(); 22 | for (let i = 0; i < 1000000000; i++) {} 23 | const end = Date.now(); 24 | console.log(end - start + 'ms'); 25 | } 26 | 27 | work(); 28 | console.log('다음 작업'); 29 | 30 | ``` 31 | 32 | 여기서 Date.now 는 현재 시간을 숫자 형태로 가져오는 자바스크립트 내장 함수입니다. 위 work 함수는, 1,000,000,000 번 루프를 돌고, 이 작업이 얼마나 걸렸는지 알려줍니다. 33 | 34 |  35 | 36 | 지금은 `work()` 함수가 호출되면, for 문이 돌아갈 때는 다른 작업은 처리하지 않고 온전히 for 문만 실행하고 있습니다. 37 | 38 | 만약 이 작업이 진행되는 동안 다른 작업도 하고 싶다면 함수를 비동기 형태로 전환을 해주어야하는데요, 그렇게 하기 위해서는 `setTimeout` 이라는 함수를 사용해주어야합니다. 39 | 40 | 코드를 다음과 같이 수정해보세요. 41 | 42 | ```javascript 43 | function work() { 44 | setTimeout(() => { 45 | const start = Date.now(); 46 | for (let i = 0; i < 1000000000; i++) {} 47 | const end = Date.now(); 48 | console.log(end - start + 'ms'); 49 | }, 0); 50 | } 51 | 52 | console.log('작업 시작!'); 53 | work(); 54 | console.log('다음 작업'); 55 | ``` 56 | 57 | `setTimeout` 함수는 첫번째 파라미터에 넣는 함수를 두번째 파라미터에 넣은 시간(ms 단위)이 흐른 후 호출해줍니다. 지금은 두번째 파라미터에 0을 넣었습니다. 따라서, 이 함수는 바로 실행이 됩니다. 0ms 이후에 실행한다는 의미이지만 실제로는 4ms 이후에 실행됩니다 [(참고)](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout#Reasons_for_delays_longer_than_specified). 이렇게 `setTimeout` 을 사용하면 우리가 정한 작업이 백그라운드에서 수행되기 때문에 기존의 코드 흐름을 막지 않고 동시에 다른 작업들을 진행 할 수 있습니다. 58 | 59 |  60 | 61 | 결과물을 보면, 작업이 시작 되고 나서, for 루프가 돌아가는 동안 다음 작업도 실행되고, for 루프가 끝나고 나서 몇 ms 걸렸는지 나타나고 있습니다. 62 | 63 | 그렇다면, 만약에 work 함수가 끝난 다음에 어떤 작업을 처리하고 싶다면 어떻게 해야 할까요? 이럴 땐, 콜백 함수를 파라미터로 전달해주면 됩니다. 콜백 함수란, 함수 타입의 값을 파라미터로 넘겨줘서, 파라미터로 받은 함수를 특정 작업이 끝나고 호출을 해주는 것을 의미합니다. 64 | 65 | ```javascript 66 | function work(callback) { 67 | setTimeout(() => { 68 | const start = Date.now(); 69 | for (let i = 0; i < 1000000000; i++) {} 70 | const end = Date.now(); 71 | console.log(end - start + 'ms'); 72 | callback(); 73 | }, 0); 74 | } 75 | 76 | console.log('작업 시작!'); 77 | work(() => { 78 | console.log('작업이 끝났어요!') 79 | }); 80 | console.log('다음 작업'); 81 | ``` 82 | 83 |  84 | 85 | 다음과 같은 작업들은 주로 비동기적으로 처리하게 됩니다. 86 | 87 | - **Ajax Web API 요청**: 만약 서버쪽에서 데이터를 받와아야 할 때는, 요청을 하고 서버에서 응답을 할 때 까지 대기를 해야 되기 때문에 작업을 비동기적으로 처리합니다. 88 | - **파일 읽기**: 주로 서버 쪽에서 파일을 읽어야 하는 상황에는 비동기적으로 처리합니다. 89 | - **암호화/복호화**: 암호화/복호화를 할 때에도 바로 처리가 되지 않고, 시간이 어느정도 걸리는 경우가 있기 때문에 비동기적으로 처리합니다. 90 | - **작업 예약**: 단순히 어떤 작업을 몇초 후에 스케쥴링 해야 하는 상황에는, setTimeout 을 사용하여 비동기적으로 처리합니다. 91 | 92 | 비동기 작업을 다룰 때에는 callback 함수 외에도 Promise, 그리고 async/await 라는 문법을 사용하여 처리 할 수 있습니다. 이번 챕터에서는 이에 대하여 알아보게 됩니다. 93 | 94 | -------------------------------------------------------------------------------- /basics/01-hello-javascript.md: -------------------------------------------------------------------------------- 1 | ## 01. Hello JavaScript! 2 | 3 | 자바스크립트는 여러분의 브라우저에서 언제든지 사용 할 수 있습니다. 만약 현재 여러분이 크롬브라우저가 아닌 다른 브라우저를 사용중이라면 크롬을 설치하여 실행해보세요. 그리고 개발자 도구를 열어보세요. 4 | 5 | 개발자 도구는 윈도우 Ctrl + Shift + I 또는 macOS Command + Option + I 키를 눌러서 열 수 있습니다. 6 | 7 | > Safari, FireFox 에도 개발자 도구가 있습니다. 단, 이 튜토리얼에서는 크롬을 사용하기에 크롬 설치를 권장드립니다. 8 | 9 | 크롬 개발자 도구에서 Console 탭을 열고 입력창에 다음 코드를 입력해보세요. 10 | 11 | ```javascript 12 | console.log('Hello JavaScript!'); 13 | ``` 14 | 15 |  16 | 17 | 위 이미지와 같이 Hello JavaScript! 가 보여졌나요? 18 | 19 | 여기서 `console.log` 는 콘솔에 특정 내용을 출력하라는 것을 의미합니다. 20 | 21 | 이번에는 조금 다른걸 해볼까요? 22 | 23 | 다음 코드를 한번 입력해보세요. 24 | 25 | ```javascript 26 | console.log(1 + 2 + 3 + 4); 27 | ``` 28 | 29 | 10 이라는 결과물이 나타났나요? 30 | 31 | 우리는 이렇게 JavaScript 를 통하여 연산을 할 수도 있답니다. 32 | 33 | 그런데 아무래도 매번 코드를 작성 할 때마다 크롬 개발자 도구에서 하는 것은 조금 불편합니다. 34 | 35 | 그래서, 여러분께 유용한 웹사이트를 소개드려볼까 합니다. 36 | 37 | 바로 [CodeSandbox](https://codesandbox.io) 이라는 사이트인데요, 코드를 작성하고 바로 결과물을 확인 할 수 있는 서비스입니다. 38 | 39 | 위 링크를 열고 우측 상단의 Create Sandbox 를 누르세요. 40 | 41 |  42 | 43 | 그 다음에 Vanilla 를 선택하세요. Vanilla 는, 다른 라이브러리 없이 자바스크립트만 사용하겠다는 의미입니다. 44 | 45 |  46 | 47 | 다음과 같은 에디터가 나타날텐데, 상단에 Fork 버튼을 누르세요. 48 | 49 |  50 | 51 | 그 다음, 52 | 53 | index.js 파일의 내용을 다 지우고 다음 코드를 입력해보세요. 54 | 55 | ```javascript 56 | console.log('안녕하세요!'); 57 | console.log('JavaScript 를 배워봅시다'); 58 | ``` 59 | 60 | 그 다음에 우측의 Console 을 누르시면 결과물이 나타납니다. 61 | 62 |  63 | 64 | 흰 페이지는 HTML 결과물을 보여주는 곳인데, 지금은 필요 없으니 이렇게 Console 창을 드래그하여 위로 쭉 끌어 올려주세요. 65 | 66 |  67 | 68 | 또는 이렇게 할 수도 있습니다. 69 | 70 |  71 | 72 | 이렇게 콘솔 탭을 옮기고 나서 다시 자바스크립트를 실행하려면, 코드에 변화를 주어야 합니다 (위 화면에서는 JavaScript 를 배워봅시다 뒤에 느낌표를 찍었습니다.) 73 | 74 | 이제 여러분은 JavaScript 를 작성하고, 실행 할 준비가 되었습니다! 75 | 76 | > CodeSandbox 에서는 코드 테마도 바꿀 수 있답니다. 77 | >  78 | -------------------------------------------------------------------------------- /basics/02-variables.md: -------------------------------------------------------------------------------- 1 | ## 02. 변수와 상수 2 | 3 | 변수와 상수에 대해서 알아봅시다. 변수와 상수는, 특정 이름에 특정 값을 담을 때 사용합니다. 4 | 5 | 예를 들어서 우리가 value 라는 이름에 1 이라는 값을 넣는다고 가정해봅시다. 6 | 7 | 그러면, 코드를 이렇게 입력하면 됩니다. 8 | 9 | ```javascript 10 | let value = 1; 11 | ``` 12 | 13 | 그러면, 앞으로 우리가 value 를 조회하면 value 는 1을 가르키게 됩니다. 예를 들어서 우리가 이전에 배웠던 console.log 를 통하여 value 값을 출력하도록 해보세요. 14 | 15 | ```javascript 16 | let value = 1; 17 | console.log(value); 18 | ``` 19 | 20 |  21 | 22 | 1이라는 값이 우측에 나타날 것입니다. 23 | 24 | 특정 이름에 특정 값을 설정하는 것. 우리는 이것을 **선언** 이라고 부릅니다. 쉽게 말하면 이제부터 value 는 1이야~ 라고 정해주는 것이죠. 25 | 26 | 값을 선언 할 때에는 두가지 종류가 있는데요, 하나는 변수이고, 하나는 상수입니다. 27 | 28 | ### 변수 29 | 30 | 변수는, 바뀔수 있는 값을 말합니다. 한번 값을 선언하고 나서 바꿀 수 있습니다. 31 | 32 | ```javascript 33 | let value = 1; 34 | console.log(value); 35 | value = 2; 36 | console.log(value); 37 | ``` 38 | 39 |  40 | 41 | 변수를 선언 할 때에는 이렇게 `let` 이라는 키워드를 사용합니다. 사용 하실 때 주의 할 점은 한번 선언했으면 똑같은 이름으로 선언하지 못합니다. 42 | 43 | 이런 코드는 오류가 발생합니다. 44 | 45 | ```javascript 46 | let value = 1; 47 | let value = 2; 48 | ``` 49 | 50 |  51 | 52 | 단, 다른 블록 범위 내에서는 똑같은 이름으로 사용이 가능하긴 한데요, 이에 대해서는 나중에 알아보겠습니다. 53 | 54 | ### 상수 55 | 56 | 상수는, 한번 선언하고 값이 바뀌지 않는 값을 의미합니다. 즉, 값이 고정적이죠. 상수를 선언 할 때에는 다음과 같이 선언합니다. 57 | 58 | ```javascript 59 | const a = 1; 60 | ``` 61 | 62 | 이렇게, 상수를 선언 할 때에는 `const` 키워드를 사용합니다. 63 | 64 | 상수를 선언하고 나면, 값을 바꿀 수 없습니다. 65 | 66 | 한번 다음 코드를 입력해보세요. 67 | 68 | ```javascript 69 | const a = 1; 70 | a = 2; 71 | ``` 72 | 73 |  74 | 75 | "Error: "a" is read-only" 라는 오류가 발생했습니다. 한번 상수로 선언했으면 값을 바꿀 수 없음을 의미합니다. 76 | 77 | 상수를 선언할 때에도 마찬가지로 한번 선언했으면 같은 이름으로 선언 할 수 없습니다. 78 | 79 | ```javascript 80 | const a = 1; 81 | const a = 2; 82 | ``` 83 | 84 |  85 | 86 | ### 이제는 더 이상 사용하지마세요, var 87 | 88 | 변수를 선언하는 또 다른 방법으로, `var` 이라는 키워드가 있습니다. 이 키워드를 이미 알고 계신 분들도 있을텐데, 모오오오던 자바스크립트에서는 더 이상 사용하지 않습니다. 89 | 90 | ```javascript 91 | var a = 1; 92 | ``` 93 | 94 | var 이 let 과 다른 주요 차이점으로는, 똑같은 이름으로 여러번 선언 할 수도 있습니다. 추가적으로, var 과 let 은 사용 할 수 있는 범위가 다른데요, 이에 대해선 다음 번에 더 자세히 알아보도록 하겠습니다. 95 | 96 | 일단, var 키워드는 그냥 모르시는걸로 하셔도 무방합니다. 97 | 98 | 추가적으로, IE9, IE10 같은 구형 브라우저에서는 let 과 const 를 사용 할 수 없습니다. 하지만, 보통 개발을 하게 될 때는 Babel 과 같은 도구를 사용하여 코드가 구형 브라우저에서도 돌아갈 수 있게끔 변환작업을 합니다. 만약에, 여러분이 나중에 별도의 도구 없이 구형 브라우저를 호환시켜야 하는 상황이 온다면 (그럴 일은 거의 없을 겁니다.) var 를 사용하게 될 수도 있습니다. 99 | 100 | ### 데이터 타입 101 | 102 | 우리가 변수나 상수를 선언하게 될 때, 숫자 외에도 다른 값들을 선언 할 수 있습니다. 종류는 굉장히 많은데요 그 중에서 가장 기본적인 것들을 알아보겠습니다. 103 | 104 | #### 숫자 (Number) 105 | 106 | 우선, 이미 사용해보았지만, 숫자는 그냥 바로 값을 대입하면 됩니다. 107 | 108 | ```javascript 109 | let value = 1; 110 | ``` 111 | 112 | #### 문자열 (String) 113 | 114 | 그리고, 텍스트 (주로, 프로그래밍 언어에서는 이를 문자열이라고 부릅니다.) 형태의 값은 작은 따옴표 혹은 큰 따옴표로 감싸서 선언합니다. 115 | 116 | ```javascript 117 | let text = 'hello'; 118 | let name = '좌봐스크립트'; 119 | ``` 120 | 121 | 작은 따옴표와 큰 따옴표 사용에 있어서 큰 차이는 없습니다. 둘다 사용하셔도 되는데, 하나만 선택하셔서 사용하시면 됩니다. 저는 개인적으로 작은 따옴표 사용을 선호합니다. 122 | 123 | CodeSandbox 에서는 작은 따옴표로 작성을 하면 자동으로 큰 따옴표로 변환을 해줄 것입니다. 자동 변환되는 것을 방지하기 위해서는 CodeSandbox의 좌측의 설정 아이콘을 누르고, .prettierrc 의 Create File 버튼을 누르고 나서 Use Single Quotes 를 활성화하세요. 124 | 125 |  126 | 127 | #### 참/거짓 (Boolean) 128 | 129 | 이번에는 boolean 이라는 것에 대해서 알아보겠습니다. boolean 은, 참 혹은 거짓 두가지 종류의 값만을 나타낼 수 있습니다. 130 | 131 | ```javascript 132 | let good = true; 133 | let loading = false; 134 | ``` 135 | 136 | 참은 true, 거짓은 false 입니다. 137 | 138 | #### null 과 undefined 139 | 140 | 자바스크립트에서는 "없음" 을 의미하는 데이터 타입이 두 종류가 있는데요, 하나는 `null` 이고 하나는 `undefined` 인데, 둘의 용도가 살짝 다릅니다. 141 | 142 | null 은 주로, 이 값이 없다! 라고 선언을 할 때 사용합니다. 143 | 144 | 영국 드라마 주인공 셜록의 드라마 대사 중에 "난 친구 같은거 없어" 라는 대사가 있습니다. 145 | 146 |  147 | 148 | ```javascript 149 | const friend = null; 150 | ``` 151 | 152 | 반면, undefined 는, 아직 값이 설정되지 않은 것을 의미합니다. 153 | 154 | 다음 코드를 입력해보세요. 155 | 156 | ```javascript 157 | let criminal; 158 | console.log(criminal); 159 | ``` 160 | 161 | criminal 이라는 변수를 선언하긴 했지만 값을 지정해주지는 않았습니다. 이를 console.log 를 통해 보여주도록 하면 undefined 라는 값이 나타나게 됩니다. 162 | 163 |  164 | 165 | null 과 undefined 는 둘 다 값이 없음을 의미하는건 맞는데, null 은 우리가 없다고, 고의적으로 설정하는 값을 의미하고, undefined 는 우리가 설정을 하지 않았기 때문에 없는 값을 의미합니다. 166 | 167 | -------------------------------------------------------------------------------- /basics/03-operator.md: -------------------------------------------------------------------------------- 1 | ## 03. 연산자 2 | 3 | 연산자에 대해서 알아봅시다. 4 | 5 | 연산자는 프로그래밍 언어에서 특정 연산을 하도록 하는 문자입니다. 6 | 7 | 예를 들어서, 우리가 변수와 상수를 배울 때 다음과 같은 코드를 작성했었지요? 8 | 9 | ```javascript 10 | let value = 1; // 변수 선언 11 | value = 2; // 대입 연산자 12 | ``` 13 | 14 | 여기서 두번째 줄에서 사용된 `=` 문자가 바로 연산자입니다. 연산자의 종류는 굉장히 많습니다. 그 중에서 `=` 는, 대입 연산자에 해당합니다. 첫번째 줄은 새로운 변수를 선언하는 것으로서, 대입 연산자에 해당하지 않습니다. 15 | 16 | ### 산술 연산자 17 | 18 | 산술 연산자는 사칙연산과 같은 작업을 하는 연산자를 의미합니다. 19 | 20 | - `+`: 덧셈 21 | - `-`: 뺼셈 22 | - `*`: 곱셈 23 | - `/`: 나눗셈 24 | 25 | 위 4가지가 가장 기본적인 산술 연산자입니다. 이 외에도 몇가지가 더 있는데요, 먼저 위 연산자들을 한번 사용해봅시다. 26 | 27 | ```javascript 28 | let a = 1 + 2; 29 | console.log(a); 30 | ``` 31 | 32 | 위 코드는 a 값을 선언 할 때 1 + 2 의 결과물을 담습니다. 따라서 콘솔에선 3 이라는 숫자가 나타나겠죠. 33 | 34 |  35 | 36 | ```javascript 37 | let a = 1 + 2 - (3 * 4) / 4; 38 | console.log(a); 39 | ``` 40 | 41 | 이렇게 우리가 계산기를 두드릴 때 처럼 할 수도 있습니다. 42 | 43 |  44 | 45 | 그리고, 이런 것도 할 수 있습니다. 이 또한 산술 연산자의 일부입니다. 46 | 47 | ```javascript 48 | let a = 1; 49 | a++; 50 | ++a; 51 | console.log(a); 52 | ``` 53 | 54 | 결과는 3이 나타납니다. `++` 는 특정 변수에 1을 바로 더해줍니다. 그런데, ++ 가 변수 이름 앞에 오는 것과 뒤에 오는것에 차이가 있습니다. 55 | 56 | ```javascript 57 | let a = 1; 58 | console.log(a++); 59 | console.log(++a); 60 | ``` 61 | 62 |  63 | 64 | `console.log(a++);` 를 할 때에는 1을 더하기 직전 값을 보여주고 65 | `console.log(++a);` 를 할 때에는 1을 더한 다음의 값을 보여준다는 차이가 있습니다. 66 | 67 | 덧셈 외에도 뺄셈도 똑같이 할 수 있습니다. 68 | 69 | ```javascript 70 | let a = 1; 71 | a--; 72 | console.log(a); 73 | ``` 74 | 75 | 결과는 0이 나타나게 됩니다. 76 | 77 | ### 대입 연산자 78 | 79 | 대입 연산자는 특정 값에 연산을 한 값을 바로 설정 할 때 사용 할 수 있는 연산자입니다. 예를 들어서 다음과 같은 코드가 있다면 80 | 81 | ```javascript 82 | let a = 1; 83 | a = a + 3; 84 | ``` 85 | 86 | 위 코드를 대입 연산자를 사용하면 다음과 같이 작성할 수 있습니다. 87 | 88 | ```javascript 89 | let a = 1; 90 | a += 3; 91 | ``` 92 | 93 | 덧셈 말고 다른 연산도 가능합니다. 94 | 95 | ```javascript 96 | let a = 1; 97 | a += 3; 98 | a -= 3; 99 | a *= 3; 100 | a /= 3; 101 | console.log(a); 102 | ``` 103 | 104 | 결과는 1이 나타나게 됩니다. 105 | 106 | ### 논리 연산자 107 | 108 | 논리 연산자는, 불리언 타입 (true 혹은 false)를 위한 연산자입니다. 논리 연산자는 다음 장에서 우리가 if 문을 배울 때 매우 유용합니다. 109 | 110 | 총 3가지가 있습니다. 111 | 112 | - `!`: NOT 113 | - `&&`: AND 114 | - `||`: OR 115 | 116 | OR의 경우엔 엔터키 위의 \ 문자를 Shift 누른 상태로 누르면 됩니다. 117 | 118 | #### NOT 119 | 120 | NOT 연산자는 true 는 false 로, false 는 true 로 바꿔줍니다. 121 | 122 | ```javascript 123 | const a = !true; 124 | console.log(a); 125 | ``` 126 | 127 | a 값은 false 입니다. 128 | 129 | ```javascript 130 | const b = !false; 131 | console.log(b); 132 | ``` 133 | 134 | b 값은 true 가 됩니다. 135 | 136 | #### AND 137 | 138 | AND 연산자는 양쪽의 값이 둘 다 true 일때만 결과물이 true 입니다. 139 | 140 | ```javascript 141 | const a = true && true; 142 | console.log(a); 143 | ``` 144 | 145 | 다음과 같은 상황엔 모두 false 입니다. 146 | 147 | ```javascript 148 | let f = false && false; 149 | f = false && true; 150 | f = true && false; 151 | ``` 152 | 153 | #### OR 154 | 155 | OR 연산자는 양쪽의 값 중 하나라도 true 라면 결과물이 true 입니다. 그리고, 두 값이 둘 다 false 일 때에만 false 입니다. 156 | 157 | 다음 상황엔 t 값은 true 입니다. 158 | 159 | ```javascript 160 | let t = true || false; 161 | t = false || true; 162 | t = true || true; 163 | ``` 164 | 165 | 반면 상황엔 false 입니다. 166 | 167 | ```javascript 168 | let f = false || false; 169 | ``` 170 | 171 | #### 연산 순서 172 | 173 | 사칙연산을 할 때 곱셈 나눗셈이 먼저고 그 다음이 덧셈 뺄셈인 것 처럼, 논리 연산자도 순서가 있습니다. 순서는 NOT -> AND -> OR 입니다. 174 | 예를 들어 다음과 같은 코드가 있다고 가정해봅시다. 175 | 176 | ```javascript 177 | const value = !((true && false) || (true && false) || !false); 178 | ``` 179 | 180 | 괄호로 감싸져있을 때에는 가장 마지막에 처리를 하니까 맨 앞 NOT 은 나중에 처리하겠습니다. 181 | 182 | 우선 NOT 을 처리합니다. 183 | 184 | ```javascript 185 | !((true && false) || (true && false) || true); 186 | ``` 187 | 188 | 그 다음엔 AND 를 처리합니다. 189 | 190 | ```javascript 191 | !(false || false || true); 192 | ``` 193 | 194 | OR 연산자를 좌측에서 우측 방향으로 처리를 하게 되면서 다음과 같이 처리됩니다. 195 | 196 | ```javascript 197 | !true; 198 | ``` 199 | 200 | 결국 결과값은 false 가 됩니다. 201 | 202 | ### 비교 연산자 203 | 204 | 비교 연산자는 두 값을 비교 할 때 사용 할 수 있습니다. 205 | 206 | #### 두 값이 일치하는지 확인 207 | 208 | ```javascript 209 | const a = 1; 210 | const b = 1; 211 | const equals = a === b; 212 | console.log(equals); 213 | ``` 214 | 215 | `===` 는 두 값이 일치하는지 확인해줍니다. 일치한다면, true, 일치하지 않는다면 false 가 나타납니다. 위 코드의 경우엔 true 가 나타나겠죠? 216 | 217 | 두 값이 일치 하는지 확인 할 때 `=` 문자를 3번 사용하는데요, 2개로도 비교를 할 수는 있습니다. 218 | 219 | ```javascript 220 | const a = 1; 221 | const b = 1; 222 | const equals = a == b; 223 | console.log(equals); 224 | ``` 225 | 226 | 위 코드는 똑같은 결과 true 를 반환하긴 하는데요, `=` 문자가 3개 있을 때와 2개 있을 떄의 차이점은 2개 있을때에는 타입 검사까지는 하지 않는다는 것입니다. 227 | 228 | 예를 들어서 `==` 를 사용하면 숫자 1과 문자 '1' 이 동일한 값으로 간주됩니다. 229 | 230 | ```javascript 231 | const a = 1; 232 | const b = '1'; 233 | const equals = a == b; 234 | console.log(equals); 235 | ``` 236 | 237 | 결과: true 238 | 239 | 그리고, 0 과 false 도 같은 값으로 간주되지요. 240 | 241 | ```javascript 242 | const a = 0; 243 | const b = false; 244 | const equals = a == b; 245 | console.log(equals); 246 | ``` 247 | 248 | 결과: true 249 | 250 | 그리고 undefined 와 null 도 같은 값으로 간주됩니다. 251 | 252 | ```javascript 253 | const a = null; 254 | const b = undefined; 255 | const equals = a == b; 256 | console.log(equals); 257 | ``` 258 | 259 | 결과: true 260 | 261 | 앞으로 여러분이 두 값이 일치하는지 비교 할 때에는 `==` 대신 `===` 를 사용 할 것을 권장 드립니다. `==` 를 사용하다보면 실수를 할 확률이 높아집니다. 262 | 263 | #### 두 값이 일치하지 않는지 확인 264 | 265 | 두 값이 일치하지 않는지 확인 할 때에는 `!==` 를 사용하면 됩니다. 266 | 267 | ```javascript 268 | const value = 'a' !== 'b'; 269 | ``` 270 | 271 | 결과물은 true 가 됩니다. 272 | 273 | `!=` 를 사용하게 되면 타입 검사를 하지 않습니다. 274 | 275 | ```javascript 276 | console.log(1 != '1'); 277 | console.log(1 !== '1'); 278 | ``` 279 | 280 | 처음엔 false, 두번째에서는 true가 나타납니다. 두 값이 일치하지 않는지 확인 할 때에도, !== 를 사용 할 것을 권장드립니다. 281 | 282 | #### 크고 작음 283 | 284 | 두 값 중에서 무엇이 더 크고 작은지 비교하기 위해서는 다음 연산자를 사용 할 수 있습니다. 285 | 286 | ```javascript 287 | const a = 10; 288 | const b = 15; 289 | const c = 15; 290 | 291 | console.log(a < b); // true 292 | console.log(b > a); // true 293 | console.log(b >= c); // true 294 | console.log(a <= c); // true 295 | console.log(b < c); // false; 296 | ``` 297 | 298 | 위 코드에서 `// false` 이런 식으로 코드의 뒷부분에 텍스트가 적혀있는데요, 이는 주석이라고 부릅니다. 코드에 메모를 다는 것이죠. 299 | 300 | 여러줄로 주석을 작성 할 때에는 다음과 같이 할 수 있습니다. 301 | 302 | ```javascript 303 | /* 304 | 여러줄로 주석 작성하기 305 | */ 306 | ``` 307 | 308 | ### 문자열 붙이기 309 | 310 | 두 문자열을 붙일 때에는 `+` 로 할 수 있습니다. 311 | 312 | ```javascript 313 | const a = '안녕'; 314 | const b = '하세요'; 315 | console.log(a + b); // 안녕하세요 316 | ``` 317 | 318 | 319 | -------------------------------------------------------------------------------- /basics/04-conditions.md: -------------------------------------------------------------------------------- 1 | ## 04. 조건문 2 | 3 | 조건문을 사용하면 특정 조건이 만족됐을 때 특정 코드를 실행할 수 있습니다. 4 | 5 | ### if 문 6 | 7 | 가장 기본적인 조건문은 if 문입니다. 8 | 9 | if문은, "~~하다면 ~~를 해라" 를 의미합니다. 10 | 11 | 예시 코드를 한번 봅시다. 12 | 13 | ```javascript 14 | const a = 1; 15 | if (a + 1 === 2) { 16 | console.log('a + 1 이 2 입니다.'); 17 | } 18 | ``` 19 | 20 | 결과는, "a + 1 이 2 입니다." 이 출력됩니다. 21 | 22 | 하지만, 만약에 여기서 a 를 0 으로 바꾼다면 어떨까요? 23 | 24 | ```javascript 25 | const a = 0; 26 | if (a + 1 === 2) { 27 | console.log('a + 1 이 2 입니다.'); 28 | } 29 | ``` 30 | 31 | 결과는, 아무것도 출력되지 않습니다. 32 | 33 | if문을 사용하면, 이렇게 특정 조건이 만족 될 때에만 특정 코드를 실행 시킬 수 있습니다. 34 | 35 | ```javascript 36 | if (조건) { 37 | 코드; 38 | } 39 | ``` 40 | 41 | 조건이 만족됐을 때 실행시킬 코드가 `{ }` 로 감싸져있는데요, 이를 코드 블록이라고 합니다. 42 | 43 | 만약에 조건이 true 가 된다면 우리가 지정한 코드가 실행되는 것이고, false 가 된다면 코드가 실행되지 않습니다. 44 | 45 | 우리가 이전에 `let` 과 `const` 를 배울 때, 다른 블록 범위에서는 똑같은 이름으로 선언 할 수도 있다고 배웠었습니다. 46 | 47 | 다음 코드를 한번 실행해보세요. 48 | 49 | ```javascript 50 | const a = 1; 51 | if (true) { 52 | const a = 2; 53 | console.log('if문 안의 a 값은 ' + a); 54 | } 55 | console.log('if문 밖의 a 값은 ' + a); 56 | ``` 57 | 58 | 위 코드에서는 if문에 조건을 true 로 설정했기 때문에 코드 블록 내부의 코드가 무조건 실행이 됩니다. 59 | 60 | 결과는 다음과 같습니다 61 | 62 | ``` 63 | "if문의 안의 a 값은 2" 64 | "if문 밖의 a 값은 1" 65 | ``` 66 | 67 | ### if-else 문 68 | 69 | if-else문은 "~~하다면 ~~하고, 그렇지 않다면 ~~해라." 를 의미합니다. 70 | 71 | 예시 코드를 볼까요? 72 | 73 | ```javascript 74 | const a = 10; 75 | if (a > 15) { 76 | console.log('a 가 15 큽니다.'); 77 | } else { 78 | console.log('a 가 15보다 크지 않습니다.'); 79 | } 80 | ``` 81 | 82 | 위 코드의 결과는 다음과 같습니다. 83 | 84 | ``` 85 | "a 가 10보다 크지 않습니다." 86 | ``` 87 | 88 | 만약에 특정 조건이 만족할 때와 만족하지 않을 때 서로 다른 코드를 실행해야 된다면 if-else 구문을 사용 할 수 있습니다. 89 | 90 | ### if-else if 문 91 | 92 | if-else if 문은 여러 조건에 따라 다른 작업을 해야 할 때 사용합니다. 93 | 94 | 예시 코드를 따라 적어보세요. 95 | 96 | ```javascript 97 | const a = 10; 98 | if (a === 5) { 99 | console.log('5입니다!'); 100 | } else if (a === 10) { 101 | console.log('10입니다!'); 102 | } else { 103 | console.log('5도 아니고 10도 아닙니다.'); 104 | } 105 | ``` 106 | 107 | 결과는 다음과 같습니다. 108 | 109 | ``` 110 | "10입니다!" 111 | ``` 112 | 113 | 한번 a 값을 5로 바꾸고 실행해보고, 7 로 바꾸고 실행해보세요. 114 | 115 | ``` 116 | a = 5 -> "5입니다!" 117 | a = 7 -> "5도 아니고 10도 아닙니다." 118 | ``` 119 | 120 | ### switch/case 문 121 | 122 | switch/case 문은 특정 값이 무엇이냐에 따라 다른 작업을 하고 싶을 때 사용합니다. 123 | 124 | 다음 예시 코드를 실행해보세요. 125 | 126 | ```javascript 127 | const device = 'iphone'; 128 | 129 | switch (device) { 130 | case 'iphone': 131 | console.log('아이폰!'); 132 | break; 133 | case 'ipad': 134 | console.log('아이패드!'); 135 | break; 136 | case 'galaxy note': 137 | console.log('갤럭시 노트!'); 138 | break; 139 | default: 140 | console.log('모르겠네요..'); 141 | } 142 | ``` 143 | 144 | device 값을 'iphone', 'ipad', 'galaxy note', 'macbook' 으로 순서대로 바꿔가면서 코드를 실행해보세요. 145 | 146 | device 값에 따라서 다른 결과가 출력되고 있나요? 147 | 148 | switch/case 문은 이와 같이 특정 값이 무엇이냐에 따라 다른 작업을 수행 할 수 있게 해줍니다. 149 | 150 | switch/case 문에서는 각 case 에서 실행할 코드를 작성하고 맨 마지막에 `break;` 를 해주어야 합니다. break 를 하지 않으면 그 다음 case 의 코드까지 실행해버립니다. 151 | 152 | 그리고, 맨 아래의 `default:` 는 device 값이 우리가 case 로 준비하지 않은 값일 경우를 의미합니다. 153 | 154 | 155 | -------------------------------------------------------------------------------- /basics/05-function.md: -------------------------------------------------------------------------------- 1 | ## 05. 함수 2 | 3 | 함수는, 특정 코드를 하나의 명령으로 실행 할 수 있게 해주는 기능입니다. 4 | 5 | 예를 들어서, 우리가 특정 값들의 합을 구하고 싶을 때는 다음과 같이 코드를 작성합니다. 6 | 7 | ```javascript 8 | const a = 1; 9 | const b = 2; 10 | const sum = a + b; 11 | ``` 12 | 13 | 한번, 이 작업을 함수로 만들어보겠습니다. 14 | 15 | ```javascript 16 | function add(a, b) { 17 | return a + b; 18 | } 19 | 20 | const sum = add(1, 2); 21 | console.log(sum); 22 | ``` 23 | 24 | 결과는 3이 됩니다. 25 | 26 | 함수를 만들 때는 `function` 키워드를 사용하며, 함수에서 어떤 값을 받아올지 정해주는데 이를 파라미터(매개변수)라고 부릅니다. 27 | 28 | 함수 내부에서 `return` 키워드를 사용하여 함수의 결과물을 지정 할 수 있습니다. 29 | 30 | 추가적으로, `return` 을 하게 되면 함수가 끝납니다. 만약 다음과 같이 코드가 작성된다면, return 아래의 코드는 호출이 안됩니다. 31 | 32 | ```javascript 33 | function add(a, b) { 34 | return a + b; 35 | console.log('호출이 되지 않는 코드!'); 36 | } 37 | 38 | const sum = add(1, 2); 39 | console.log(sum); 40 | ``` 41 | 42 | 43 | ### 연습 44 | 45 | 함수 사용을 연습해봅시다. 46 | 47 | #### Hello, name! 48 | 49 | name 이라는 파라미터를 넣으면 콘솔에 'Hello name!' 이라는 결과를 출력하는 코드를 작성해봅시다. 50 | 51 | ```javascript 52 | function hello(name) { 53 | console.log('Hello, ' + name + '!'); 54 | } 55 | hello('velopert'); 56 | ``` 57 | 58 | 결과물은 다음과 같습니다. 59 | 60 | ``` 61 | "Hello, velopert!" 62 | ``` 63 | 64 | console.log 를 하게 될 때 우리는 문자열을 조합하기 위해서 `+` 연산자를 사용했습니다. 이렇게 문자열을 조합 할 때 `+` 를 사용해도 큰 문제는 없지만, 더욱 편하게 조합을 하는 방법이 있습니다. 바로, ES6 의 템플릿 리터럴 (Template Literal)이라는 문법을 사용하는 것 입니다. 65 | 66 | > **ES6 가 뭔가요?** 67 | > 68 | > ES6 는 ECMAScript6 를 의미하며, 자바스크립트의 버전을 가르킵니다. ES6는 2015년에 도입이 되었습니다. ES6 는 ES2015 라고 불리기도 합니다. 그리고 2015년 이후에 계속해서 새로운 자바스크립트 버전이 나오고 있습니다. ES7(ES2016) ES8(ES2017) ES9(ES2018) ES10(ES2019).. 새로운 자바스크립트 버전이 나올때마다 새로운 문법이 소개됩니다. 69 | > 70 | > 브라우저 버전에 따라 지원되는 자바스크립트 버전이 다릅니다. 하지만, 보통 웹 개발을 할 때에는 Babel 이라는 도구를 사용하여 최신 버전의 자바스크립트가 구버전의 브라우저에서도 실행되도록 할 수 있습니다. (정확히는, 최신버전 자바스크립트를 구버전 형태로 변환하는 작업을 거칩니다.) 71 | 72 | 템플릿 리터럴을 사용하여 구현을 해봅시다. 73 | 74 | ```javascript 75 | function hello(name) { 76 | console.log(`Hello, ${name}!`); 77 | } 78 | hello('velopert'); 79 | ``` 80 | 81 | #### 점수를 성적등급으로 변환하기 82 | 83 | 이번에는 점수가 주어졌을 때 A, B, C, D, F 등급을 반환하는 함수를 만들어봅시다. 84 | 85 | ```javascript 86 | function getGrade(score) { 87 | if (score === 100) { 88 | return 'A+'; 89 | } else if (score >= 90) { 90 | return 'A'; 91 | } else if (score === 89) { 92 | return 'B+'; 93 | } else if (score >= 80) { 94 | return 'B'; 95 | } else if (score === 79) { 96 | return 'C+'; 97 | } else if (score >= 70) { 98 | return 'C'; 99 | } else if (score === 69) { 100 | return 'D+'; 101 | } else if (score >= 60) { 102 | return 'D'; 103 | } else { 104 | return 'F'; 105 | } 106 | } 107 | 108 | const grade = getGrade(90); 109 | console.log(grade); 110 | ``` 111 | 112 | grade 가 90 일 때에는 결과가 A 가 됩니다. 113 | 114 | ### 화살표 함수 115 | 116 | 함수를 선언하는 방식 중 또 다른 방법은 화살표 함수 문법을 사용 하는 것 입니다. 117 | 118 | ```javascript 119 | const add = (a, b) => { 120 | return a + b; 121 | }; 122 | 123 | console.log(add(1, 2)); 124 | ``` 125 | 126 | `function` 키워드 대신에 `=>` 문자를 사용해서 함수를 구현했는데요, 화살표의 좌측에는 함수의 파라미터, 화살표의 우측에는 코드 블록이 들어옵니다. 127 | 128 | 그런데, 만약에 위와 같이 코드 블록 내부에서 바로 return 을 하는 경우는 다음과 같이 줄여서 쓸 수도 있습니다. 129 | 130 | ```javascript 131 | const add = (a, b) => a + b; 132 | console.log(add(1, 2)); 133 | ``` 134 | 135 | 아까 만들었던 getGrade 함수처럼 여러 줄로 구성되어있는 경우에는 코드 블록을 만들어야합니다. 136 | 137 | ```javascript 138 | const getGrade = score => { 139 | if (score === 100) { 140 | return 'A+'; 141 | } else if (score >= 90) { 142 | return 'A'; 143 | } else if (score === 89) { 144 | return 'B+'; 145 | } else if (score >= 80) { 146 | return 'B'; 147 | } else if (score === 79) { 148 | return 'C+'; 149 | } else if (score >= 70) { 150 | return 'C'; 151 | } else if (score === 69) { 152 | return 'D+'; 153 | } else if (score >= 60) { 154 | return 'D'; 155 | } else { 156 | return 'F'; 157 | } 158 | }; 159 | const grade = getGrade(90); 160 | console.log(grade); 161 | ``` 162 | 163 | 화살표 함수와 일반 function 으로 만든 함수와의 주요 차이점은 화살표 함수에서 가르키는 this 와 function 에서 가르키는 this 가 서로 다르다는 건데요, 이에 대한 자세한 내용은 나중에 알아보도록 하겠습니다. 164 | 165 | 166 | -------------------------------------------------------------------------------- /basics/06-object.md: -------------------------------------------------------------------------------- 1 | ## 06. 객체 2 | 3 | 객체는 우리가 변수 혹은 상수를 사용하게 될 때 하나의 이름에 여러 종류의 값을 넣을 수 있게 해줍니다. 4 | 5 | ```javascript 6 | const dog = { 7 | name: '멍멍이', 8 | age: 2 9 | }; 10 | 11 | console.log(dog.name); 12 | console.log(dog.age); 13 | ``` 14 | 15 | 결과물은 다음과 같습니다. 16 | 17 | ``` 18 | 멍멍이 19 | 2 20 | ``` 21 | 22 | 객체를 선언 할 때에는 이렇게 `{ }` 문자 안에 원하는 값들을 넣어주면 됩니다. 값을 집어 넣을 때에는 23 | 24 | ``` 25 | 키: 원하는 값 26 | ``` 27 | 28 | 형태로 넣으며, 키에 해당하는 부분은 공백이 없어야합니다. 만약에 공백이 있어야 하는 상황이라면 이를 따옴표로 감싸서 문자열로 넣어주면 됩니다. 29 | 30 | ```javascript 31 | const sample = { 32 | 'key with space': true 33 | }; 34 | ``` 35 | 36 | 한번 영화 어벤져스의 캐릭터 아이언맨과 캡틴 아메리카의 정보를 객체안에 집어넣어봅시다. 37 | 38 | ```javascript 39 | const ironMan = { 40 | name: '토니 스타크', 41 | actor: '로버트 다우니 주니어', 42 | alias: '아이언맨' 43 | }; 44 | 45 | const captainAmerica = { 46 | name: '스티븐 로저스', 47 | actor: '크리스 에반스', 48 | alias: '캡틴 아메리카' 49 | }; 50 | 51 | console.log(ironMan); 52 | console.log(captainAmerica); 53 | ``` 54 | 55 |  56 | 57 | 결과물이 잘 출력 됐나요? 58 | 59 | ### 함수에서 객체를 파라미터로 받기 60 | 61 | 함수를 새로 만들어서 방금 만든 객체를 파라미터로 받아와서 사용해봅시다. 62 | 63 | ```javascript 64 | const ironMan = { 65 | name: '토니 스타크', 66 | actor: '로버트 다우니 주니어', 67 | alias: '아이언맨' 68 | }; 69 | 70 | const captainAmerica = { 71 | name: '스티븐 로저스', 72 | actor: '크리스 에반스', 73 | alias: '캡틴 아메리카' 74 | }; 75 | 76 | function print(hero) { 77 | const text = `${hero.alias}(${hero.name}) 역할을 맡은 배우는 ${ 78 | hero.actor 79 | } 입니다.`; 80 | console.log(text); 81 | } 82 | 83 | print(ironMan); 84 | print(captainAmerica); 85 | ``` 86 | 87 | 결과물이 다음과 같이 나타나나요? 88 | 89 | ``` 90 | 아이언맨(토니 스타크) 역할을 맡은 배우는 로버트 다우니 주니어 입니다. 91 | 캡틴 아메리카(스티븐 로저스) 역할을 맡은 배우는 크리스 에반스 입니다. 92 | ``` 93 | 94 | 위 코드에서는 줄이 너무 길어지는것을 방지하기 위하여 `${hero.actor}` 가 사용되는 부분에서 새 줄이 입력되었습니다. 이는 없어도 무방합니다만, 코드 샌드박스에서 저장시 자동으로 새 줄을 입력하게 됩니다. 이러한 기능을 방지하고 싶다면, 코드샌드박스 좌측의 설정 아이콘을 누르고 .prettierrc 를 열어서 PrintWidth 를 120 정도로 늘리시면 됩니다. 95 | 96 | ### 객체 비구조화 할당 97 | 98 | print 함수를 보시면 파라미터로 받아온 hero 내부의 값을 조회 할 때 마다 `hero.` 를 입력하고 있는데, 객체 비구조화 할당이라는 문법을 사용하면 코드를 더욱 짧고 보기 좋게 작성 할 수 있습니다. 99 | 100 | > 이 문법은 "객체 구조 분해" 라고 불리기도 합니다. 101 | 102 | ```javascript 103 | const ironMan = { 104 | name: '토니 스타크', 105 | actor: '로버트 다우니 주니어', 106 | alias: '아이언맨' 107 | }; 108 | 109 | const captainAmerica = { 110 | name: '스티븐 로저스', 111 | actor: '크리스 에반스', 112 | alias: '캡틴 아메리카' 113 | }; 114 | 115 | function print(hero) { 116 | const { alias, name, actor } = hero; 117 | const text = `${alias}(${name}) 역할을 맡은 배우는 ${actor} 입니다.`; 118 | console.log(text); 119 | } 120 | 121 | print(ironMan); 122 | print(captainAmerica); 123 | ``` 124 | 125 | 똑같은 결과가 나타났나요? 126 | 127 | ```javascript 128 | const { alias, name, actor } = hero; 129 | ``` 130 | 131 | 이 코드가 객체에서 값들을 추출해서 새로운 상수로 선언해 주는 것 입니다. 132 | 133 | 여기서 더 나아가면, 파라미터 단계에서 객체 비구조화 할당을 할 수도 있습니다. 134 | 135 | ```javascript 136 | const ironMan = { 137 | name: '토니 스타크', 138 | actor: '로버트 다우니 주니어', 139 | alias: '아이언맨' 140 | }; 141 | 142 | const captainAmerica = { 143 | name: '스티븐 로저스', 144 | actor: '크리스 에반스', 145 | alias: '캡틴 아메리카' 146 | }; 147 | 148 | function print({ alias, name, actor }) { 149 | const text = `${alias}(${name}) 역할을 맡은 배우는 ${actor} 입니다.`; 150 | console.log(text); 151 | } 152 | 153 | print(ironMan); 154 | print(captainAmerica); 155 | ``` 156 | 157 | 어떤가요? 코드가 처음보다 훨씬 깔끔해졌지요? 158 | 159 | ### 객체 안에 함수 넣기 160 | 161 | 객체 안에 함수를 넣을 수도 있습니다. 한번 다음 코드를 실행해보세요. 162 | 163 | ```javascript 164 | const dog = { 165 | name: '멍멍이', 166 | sound: '멍멍!', 167 | say: function say() { 168 | console.log(this.sound); 169 | } 170 | }; 171 | 172 | dog.say(); 173 | ``` 174 | 175 | 결과는 다음과 같습니다. 176 | 177 | ``` 178 | 멍멍! 179 | ``` 180 | 181 | 함수가 객체안에 들어가게 되면, `this` 는 자신이 속해있는 객체를 가르키게 됩니다. 182 | 183 | 함수를 선언 할 때에는 이름이 없어도 됩니다. 184 | 185 | ```javascript 186 | const dog = { 187 | name: '멍멍이', 188 | sound: '멍멍!', 189 | say: function() { 190 | console.log(this.sound); 191 | } 192 | }; 193 | 194 | dog.say(); 195 | ``` 196 | 197 | 이전과 똑같이 작동 할 것입니다. 198 | 199 | 객체 안에 함수를 넣을 때, 화살표 함수로 선언한다면 제대로 작동하지 않습니다. 200 | 201 |  202 | 203 | 이유는, function 으로 선언한 함수는 this 가 제대로 자신이 속한 객체를 가르키게 되는데, 화살표 함수는 그렇지 않기 때문입니다. 204 | 205 | ## Getter 함수와 Setter 함수 206 | 207 | 객체 안에 Getter 함수와 Setter 함수를 설정하는 방법을 알아봅시다. 객체를 만들고 나면, 다음과 같이 객체안의 값을 수정 할 수도 있는데요, 208 | 209 | ```javascript 210 | const numbers = { 211 | a: 1, 212 | b: 2 213 | }; 214 | 215 | numbers.a = 5; 216 | console.log(numbers); 217 | ``` 218 | 219 |  220 | 221 | Getter 함수와 Setter 함수를 사용하게 되면 특정 값을 바꾸려고 하거나, 특정 값을 조회하려고 할 때 우리가 원하는 코드를 실행 시킬 수 있습니다. 222 | 223 | 다음 코드를 따라 적어보세요. 224 | 225 | ```javascript 226 | const numbers = { 227 | a: 1, 228 | b: 2, 229 | get sum() { 230 | console.log('sum 함수가 실행됩니다!'); 231 | return this.a + this.b; 232 | } 233 | }; 234 | 235 | console.log(numbers.sum); 236 | numbers.b = 5; 237 | console.log(numbers.sum); 238 | ``` 239 | 240 |  241 | 242 | 우리는 `numbers.sum()` 을 한 것이 아니라 `number.sum` 을 조회했을 뿐인데, 함수가 실행되고 그 결과값이 출력되었습니다. 243 | 244 | 이런식으로 Getter 함수는 특정 값을 조회 할 때 우리가 설정한 함수로 연산된 값을 반환합니다. 245 | 246 | 이번에는 Setter 함수를 사용해봅시다. 247 | 248 | ```javascript 249 | const numbers = { 250 | _a: 1, 251 | _b: 2, 252 | sum: 3, 253 | calculate() { 254 | console.log('calculate'); 255 | this.sum = this._a + this._b; 256 | }, 257 | get a() { 258 | return this._a; 259 | }, 260 | get b() { 261 | return this._b; 262 | }, 263 | set a(value) { 264 | console.log('a가 바뀝니다.'); 265 | this._a = value; 266 | this.calculate(); 267 | }, 268 | set b(value) { 269 | console.log('b가 바뀝니다.'); 270 | this._b = value; 271 | this.calculate(); 272 | } 273 | }; 274 | 275 | console.log(numbers.sum); 276 | numbers.a = 5; 277 | numbers.b = 7; 278 | numbers.a = 9; 279 | console.log(numbers.sum); 280 | console.log(numbers.sum); 281 | console.log(numbers.sum); 282 | ``` 283 | 284 |  285 | 286 | Setter 함수를 설정 할 때에는 함수의 앞부분에 `set` 키워드를 붙입니다. 287 | 288 | Setter 함수를 설정하고 나면, `numbers.a = 5` 이렇게 값을 설정했을 때 5 를 함수의 파라미터로 받아오게 됩니다. 위 코드에서는 객체 안에 \_a, \_b 라는 숫자를 선언해주고, 이 값들을 위한 Getter 와 Setter 함수를 설정해주었습니다. 289 | 290 | 아까 전에는 만든 객체에서는 numbers.sum 이 조회 될 때마다 덧셈이 이루어졌었지만, 이제는 a 혹은 b 값이 바뀔 때마다 sum 값을 연산합니다. 291 | 292 | 293 | -------------------------------------------------------------------------------- /basics/07-array.md: -------------------------------------------------------------------------------- 1 | ## 07. 배열 2 | 3 | 이번에는 배열을 배워봅시다. 이전에 배운 객체는 한 변수 혹은 상수에 여러가지 정보를 담기 위함이였다면, 배열은 여러개의 항목들이 들어있는 리스트와 같습니다. 4 | 5 | 예를 들어서 숫자 배열을 선언해봅시다. 6 | 7 | ```javascript 8 | const array = [1, 2, 3, 4, 5]; 9 | ``` 10 | 11 | 배열을 선언 할 때에는 이렇게 `[ ]` 안에 감싸주시면 됩니다. 12 | 13 | 배열 안에는 어떤 값이던지 넣을 수 있습니다. 14 | 15 | 예를 들어서, 객체 배열을 만들어볼까요? 16 | 17 | ```javascript 18 | const objects = [{ name: '멍멍이' }, { name: '야옹이' }]; 19 | ``` 20 | 21 | 배열을 선언하고 나서, n 번째 항목을 조회하고 싶을 땐 다음과 같이 할 수 있습니다. 22 | 23 | ```javascript 24 | objects[n]; 25 | ``` 26 | 27 | 한번 다음 코드를 입력해보세요. 28 | 29 | ```javascript 30 | const objects = [{ name: '멍멍이' }, { name: '야옹이' }]; 31 | 32 | console.log(objects); 33 | console.log(objects[0]); 34 | console.log(objects[1]); 35 | ``` 36 | 37 |  38 | 39 | 여기서 주의하실 점은, 첫번째 항목이 `objects[1]` 이 아니라 `objects[0]` 이라는 것 입니다. 40 | 41 | 여기서 `objects[1]` 이 두번째 항목입니다. 42 | 43 | ### 배열에 새 항목 추가하기 44 | 45 | 배열에 새로운 항목을 추가 할 때에는 배열이 지니고있는 내장 함수인 `push` 함수를 사용합니다. 46 | 47 | 다음 코드를 실행해보세요. 48 | 49 | ```javascript 50 | const objects = [{ name: '멍멍이' }, { name: '야옹이' }]; 51 | 52 | objects.push({ 53 | name: '멍뭉이' 54 | }); 55 | 56 | console.log(objects); 57 | ``` 58 | 59 |  60 | 61 | 잘 추가 됐나요? 62 | 63 | ### 배열의 크기 알아내기 64 | 65 | 배열의 크기를 알아낼 때에는 배열의 `length` 값을 확인합니다. 66 | 67 | ```javascript 68 | const objects = [{ name: '멍멍이' }, { name: '야옹이' }]; 69 | 70 | console.log(objects.length); 71 | 72 | objects.push({ 73 | name: '멍뭉이' 74 | }); 75 | 76 | console.log(objects.length); 77 | ``` 78 | 79 |  80 | 81 | length 가 2에서 3으로 올라갔나요? 82 | 83 | 배열이 push 와 length 말고도 다양한 기능을 가지고 있습니다. 이에 대해선 나중에 다시 알아보겠습니다. 84 | 85 | 86 | -------------------------------------------------------------------------------- /basics/08-loop.md: -------------------------------------------------------------------------------- 1 | ## 08. 반복문 2 | 3 | 반복문은 특정 작업을 반복적으로 할 때 사용할 수 있는 구문입니다. 4 | 5 | ### for 6 | 7 | for 문은 가장 기본적인 반복문입니다. 특정 값에 변화를 주어가면서 우리가 정한 조건이 만족된다면 계속 반복합니다. 8 | 9 | 한번 다음 코드를 따라 적어보세요. 10 | 11 | ```javascript 12 | for (let i = 0; i < 10; i++) { 13 | console.log(i); 14 | } 15 | ``` 16 | 17 |  18 | 19 | 결과가 0부터 9까지 잘 나타났나요? 20 | 21 | for 문을 다음과 같이 사용합니다. 22 | 23 | ```javascript 24 | for (초기 구문; 조건 구문; 변화 구문;) { 25 | 코드 26 | } 27 | ``` 28 | 29 | for 문을 사용 할 때 보통 `i++` 를 해서 1씩 증감하는 형태로 사용합니다. 그런데, 1씩 빼는 형태도 가능합니다. 다음 코드를 한번 실행해보세요. 30 | 31 | ```javascript 32 | for (let i = 10; i > 0; i--) { 33 | console.log(i); 34 | } 35 | ``` 36 | 37 |  38 | 39 | 10부터 1까지 결과가 잘 나타났나요? 40 | 41 | for 문은 이렇게 숫자에 변화를 주어가면서 반복적으로 작업을 실행합니다. 42 | 43 | #### 배열과 for 44 | 45 | 이번에는 우리가 이전에 배운 배열과 for 문을 함꼐 활용해보겠습니다. 다음 코드를 작성해보세요. 46 | 47 | ```javascript 48 | const names = ['멍멍이', '야옹이', '멍뭉이']; 49 | 50 | for (let i = 0; i < names.length; i++) { 51 | console.log(names[i]); 52 | } 53 | ``` 54 | 55 | 이렇게 하면 names 배열 안에있는 원소들을 하나하나 나열 할 수 있습니다. 56 | 57 |  58 | 59 | ### while 60 | 61 | while문은 특정 조건이 참이라면 계속해서 반복하는 반복문입니다. for 문은 특정 숫자를 가지고 숫자의 값을 비교하고, 증감해주면서 반복을 한다면, while문은 조건을 확인만 하면서 반복을 합니다. 때문에, 조건문 내부에서 변화를 직접 주어야 합니다. 62 | 63 | 우리가 가장 처음 작성했던 0 부터 9 까지 콘솔에 출력을하는 반복문을 while 문으로 구현해보겠습니다. 64 | 65 | ```javascript 66 | let i = 0; 67 | while (i < 10) { 68 | console.log(i); 69 | i++; 70 | } 71 | ``` 72 | 73 | while 문을 사용 할 때에는 조건문이 언젠간 false 가 되도록 신경쓰셔야 합니다. 만약에 언젠간 false 로 전환이 되지 않는다면 반복문이 끝나지 않고 영원히 반복됩니다. 74 | 75 | ### for...of 76 | 77 | `for...of`문은 배열에 관한 반복문을 돌리기 위해서 만들어진 반복문입니다. 78 | 79 | > 사실 이 구문은 배워놔도 사용 할 일이 별로 없습니다. 보통 배열을 반복할때에는 배열의 내장함수를 많이 사용합니다. 그래도 알아는 둡시다. 80 | 81 | ```javascript 82 | let numbers = [10, 20, 30, 40, 50]; 83 | for (let number of numbers) { 84 | console.log(number); 85 | } 86 | ``` 87 | 88 |  89 | 90 | ### 객체를 위한 반복문 for...in 91 | 92 | 객체를 위한 반복문을 알아보기 전에, 객체의 정보를 배열 형태로 받아올 수 있는 함수 몇가지를 알아보겠습니다. 93 | 94 | ```javascript 95 | const doggy = { 96 | name: '멍멍이', 97 | sound: '멍멍', 98 | age: 2 99 | }; 100 | 101 | console.log(Object.entries(doggy)); 102 | console.log(Object.keys(doggy)); 103 | console.log(Object.values(doggy)); 104 | ``` 105 | 106 |  107 | 108 | 각 함수의 역할은 다음과 같습니다. 109 | 110 | - `Object.entries`: `[[키, 값], [키, 값]]` 형태의 배열로 변환 111 | - `Object.keys`: `[키, 키, 키]` 형태의 배열로 변환 112 | - `Object.values`: `[값, 값, 값]` 형태의 배열로 변환 113 | 114 | 객체가 지니고 있는 값에 대하여 반복을 하고 싶다면 위 함수들을 사용하셔도 되고, `for...in` 구문을 사용하셔도 됩니다. 115 | 116 | ```javascript 117 | const doggy = { 118 | name: '멍멍이', 119 | sound: '멍멍', 120 | age: 2 121 | }; 122 | 123 | for (let key in doggy) { 124 | console.log(`${key}: ${doggy[key]}`); 125 | } 126 | ``` 127 | 128 |  129 | 130 | ### break 와 continue 131 | 132 | 반복문 안에서는 `break` 와 `continue` 를 통하여 반복문에서 벗어나거나, 그 다음 루프를 돌게끔 할 수 있습니다. 133 | 134 | ```javascript 135 | for (let i = 0; i < 10; i++) { 136 | if (i === 2) continue; // 다음 루프를 실행 137 | console.log(i); 138 | if (i === 5) break; // 반복문을 끝내기 139 | } 140 | ``` 141 | 142 | i 가 2 일땐 `continue` 를 하여 원래 console.log 를 해야 하지만 그 코드를 수행하지 않고 바로 3으로 넘어갑니다. 143 | 144 | i 가 5 일땐 `break` 를하여 반복문을 종료시킵니다. 145 | 146 |  147 | 148 | ### 연습 149 | 150 | numbers 라는 배열을 파라미터로 받아서 총합을 구하는 함수를 만들어봅시다. 151 | 152 | ```javascript 153 | function sumOf(numbers) { 154 | let sum = 0; 155 | for (let i = 0; i < numbers.length; i++) { 156 | sum += numbers[i]; 157 | } 158 | return sum; 159 | } 160 | 161 | const result = sumOf([1, 2, 3, 4, 5]); 162 | console.log(result); 163 | ``` 164 | 165 | 결과는 15 입니다. 166 | 167 | ### 퀴즈 168 | 169 | 숫자로 이루어진 배열이 주어졌을 때, 해당 숫자 배열안에 들어있는 숫자 중 3보다 큰 숫자로만 이루어진 배열을 새로 만들어서 반환해보세요. 170 | 171 | ```javascript 172 | function biggerThanThree(numbers) { 173 | /* 구현해보세요 */ 174 | } 175 | 176 | const numbers = [1, 2, 3, 4, 5, 6, 7]; 177 | console.log(biggerThanThree(numbers)); // [4, 5, 6, 7] 178 | ``` 179 | 180 | 다음 링크를 열어서 문제를 풀어보세요. 181 | 182 | [](https://codesandbox.io/s/x3lkzz0m4p?fontsize=14) 183 | 184 |  185 | 186 | 페이지에 들어가면 우측에 Test 탭을 누르면 테스트가 실패했다는 것을 보여줍니다. 해당 함수를 구현하고 나면 다음과 같이 통과가 됩니다. 187 | 188 |  189 | 190 | [정답](https://codesandbox.io/s/lro75070q7?fontsize=14) 191 | 192 | 193 | -------------------------------------------------------------------------------- /basics/09-array-functions.md: -------------------------------------------------------------------------------- 1 | ## 09. 배열 내장함수 2 | 3 | 이번에는 배열을 다룰 때 알고있으면 너무나 유용한 다양한 내장 함수들에 대하여 알아보겠습니다. 4 | 5 | ### forEach 6 | 7 | `forEach` 는 가장 쉬운 배열 내장함수입니다. 기존에 우리가 배웠던 for 문을 대체 시킬 수 있습니다. 예를 들어서 다음과 같은 텍스트 배열이 있다고 가정해봅시다. 8 | 9 | ```javascript 10 | const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지']; 11 | ``` 12 | 13 | 만약, 배열 안에 있는 모든 원소들을 모두 출력해야 한다면 for 문을 사용하여 다음과 같이 구현 할 수 있는데요, 14 | 15 | ```javascript 16 | const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지']; 17 | 18 | for (let i = 0; i < superheroes.length; i++) { 19 | console.log(superheroes[i]); 20 | } 21 | ``` 22 | 23 | 배열의 forEach 함수를 사용하면 다음과 같이 구현 할 수 있습니다. 24 | 25 | ```javascript 26 | const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지']; 27 | 28 | superheroes.forEach(hero => { 29 | console.log(hero); 30 | }); 31 | ``` 32 | 33 | forEach 함수의 파라미터로는, 각 원소에 대하여 처리하고 싶은 코드를 함수로 넣어줍니다. 이 함수의 파라미터 hero는 각 원소를 가르키게 됩니다. 34 | 35 | 이렇게 함수형태의 파라미터를 전달하는 것을 콜백함수 라고 부릅니다. 함수를 등록해주면, forEach 가 실행을 해주는 거죠. 36 | 37 | ### map 38 | 39 | `map` 은 배열 안의 각 원소를 변환 할 때 사용 되며, 이 과정에서 새로운 배열이 만들어집니다. 40 | 41 | 예를 들어서 다음과 같은 배열이 있다고 가정해봅시다. 42 | 43 | ```javascript 44 | const array = [1, 2, 3, 4, 5, 6, 7, 8]; 45 | ``` 46 | 47 | 만약에 배열 안의 모든 숫자를 제곱해서 새로운 배열을 만들고 싶다면 어떻게 해야 할까요? map 함수를 사용하지 않고 우리가 지금까지 배운 지식들을 활용하면 다음과 같이 구현 할 수 있습니다. 48 | 49 | ```javascript 50 | const array = [1, 2, 3, 4, 5, 6, 7, 8]; 51 | 52 | const squared = []; 53 | for (let i = 0; i < array.length; i++) { 54 | squared.push(array[i] * array[i]); 55 | } 56 | 57 | console.log(squared); 58 | ``` 59 | 60 | 또는 방금 배운 forEach 를 쓰면 다음과 같이 구현 할 수도 있겠죠 61 | 62 | ```javascript 63 | const array = [1, 2, 3, 4, 5, 6, 7, 8]; 64 | 65 | const squared = []; 66 | 67 | array.forEach(n => { 68 | squared.push(n * n); 69 | }); 70 | 71 | console.log(squared); 72 | ``` 73 | 74 | 결과는 다음과 같습니다. 75 | 76 | ``` 77 | [1, 4, 9, 16, 25, 36, 49, 64]; 78 | ``` 79 | 80 | 만약 map 을 사용하면 이를 더 짧은 코드를 사용하여 구현 할 수 있습니다. 81 | 82 | ```javascript 83 | const array = [1, 2, 3, 4, 5, 6, 7, 8]; 84 | 85 | const square = n => n * n; 86 | const squared = array.map(square); 87 | console.log(squared); 88 | ``` 89 | 90 | 똑같은 결과가 나타났나요? 91 | 92 | map 함수의 파라미터로는 변화를 주는 함수를 전달해줍니다. 이를 변화함수라고 부르도록 하겠습니다. 93 | 94 | 현재 우리의 변화함수 square 는 파라미터 n 을 받아와서 이를 제곱해줍니다. 95 | 96 | array.map 함수를 사용 할 때 square 를 변화함수로 사용함으로서, 내부의 모든 값에 대하여 제곱을 해서 새로운 배열을 생성하였습니다. 97 | 98 | 변화 함수를 꼭 이름을 붙여서 선언 할 필요는 없습니다. 코드를 다음과 같이 작성해도 됩니다. 99 | 100 | ```javascript 101 | const squared = array.map(n => n * n); 102 | console.log(squared); 103 | ``` 104 | 105 | ### indexOf 106 | 107 | `indexOf` 는 원하는 항목이 몇번째 원소인지 찾아주는 함수입니다. 108 | 109 | 예를 들어서 다음과 같은 배열이 있을 때 110 | 111 | ```javascript 112 | const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지']; 113 | ``` 114 | 115 | 토르가 몇번째 항목인지 알고싶다고 가정해봅시다. 116 | 117 | 그렇다면, 이렇게 입력 할 수 있습니다. 118 | 119 | ```javascript 120 | const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지']; 121 | const index = superheroes.indexOf('토르'); 122 | console.log(index); 123 | ``` 124 | 125 | 결과는 2가 나타납니다. 126 | 127 | index 값은 0 부터 시작하기 때문에 128 | 0: 아이언맨 129 | 1: 캡틴 아메리카 130 | 2: 토르 131 | 132 | 이렇게 돼서 2라는 값이 나타나는 것 입니다. 133 | 134 | ### findIndex 135 | 136 | 만약에 배열 안에 있는 값이 숫자, 문자열, 또는 불리언이라면 찾고자하는 항목이 몇번째 원소인지 알아내려면 indexOf 를 사용하면 됩니다. 하지만, 배열 안에 있는 값이 객체이거나, 배열이라면 indexOf 로 찾을 수 없습니다. 137 | 138 | 예를 들어서 다음과 같은 배열이 있다고 가정해봅시다. 139 | 140 | ```javascript 141 | const todos = [ 142 | { 143 | id: 1, 144 | text: '자바스크립트 입문', 145 | done: true 146 | }, 147 | { 148 | id: 2, 149 | text: '함수 배우기', 150 | done: true 151 | }, 152 | { 153 | id: 3, 154 | text: '객체와 배열 배우기', 155 | done: true 156 | }, 157 | { 158 | id: 4, 159 | text: '배열 내장함수 배우기', 160 | done: false 161 | } 162 | ]; 163 | ``` 164 | 165 | 여기서 만약 id 가 3 인 객체가 몇번째인지 찾으러면, `findIndex` 함수에 검사하고자 하는 조건을 반환하는 함수를 넣어서 찾을 수 있습니다. 166 | 167 | ```javascript 168 | const todos = [ 169 | { 170 | id: 1, 171 | text: '자바스크립트 입문', 172 | done: true 173 | }, 174 | { 175 | id: 2, 176 | text: '함수 배우기', 177 | done: true 178 | }, 179 | { 180 | id: 3, 181 | text: '객체와 배열 배우기', 182 | done: true 183 | }, 184 | { 185 | id: 4, 186 | text: '배열 내장함수 배우기', 187 | done: false 188 | } 189 | ]; 190 | 191 | const index = todos.findIndex(todo => todo.id === 3); 192 | console.log(index); 193 | ``` 194 | 195 | 결과는 2가 나타납니다. 196 | 197 | ### find 198 | 199 | `find` 함수는 `findIndex` 랑 비슷한데, 찾아낸 값이 몇번째인지 알아내는 것이 아니라, 찾아낸 값 자체를 반환합니다. 200 | 201 | ```javascript 202 | const todos = [ 203 | { 204 | id: 1, 205 | text: '자바스크립트 입문', 206 | done: true 207 | }, 208 | { 209 | id: 2, 210 | text: '함수 배우기', 211 | done: true 212 | }, 213 | { 214 | id: 3, 215 | text: '객체와 배열 배우기', 216 | done: true 217 | }, 218 | { 219 | id: 4, 220 | text: '배열 내장함수 배우기', 221 | done: false 222 | } 223 | ]; 224 | 225 | const todo = todos.find(todo => todo.id === 3); 226 | console.log(todo); 227 | ``` 228 | 229 | 결과는 다음과 같습니다. 230 | 231 | ```javascript 232 | {id: 3, text: "객체와 배열 배우기", done: true} 233 | ``` 234 | 235 | ### filter 236 | 237 | `filter` 함수는 배열에서 특정 조건을 만족하는 값들만 따로 추출하여 새로운 배열을 만듭니다. 예를 들어서, 우리가 방금 만들었던 todos 배열에서 done 값이 false 인 항목들만 따로 추출해서 새로운 배열을 만들어봅시다. 238 | 239 | ```javascript 240 | const todos = [ 241 | { 242 | id: 1, 243 | text: '자바스크립트 입문', 244 | done: true 245 | }, 246 | { 247 | id: 2, 248 | text: '함수 배우기', 249 | done: true 250 | }, 251 | { 252 | id: 3, 253 | text: '객체와 배열 배우기', 254 | done: true 255 | }, 256 | { 257 | id: 4, 258 | text: '배열 내장함수 배우기', 259 | done: false 260 | } 261 | ]; 262 | 263 | const tasksNotDone = todos.filter(todo => todo.done === false); 264 | console.log(tasksNotDone); 265 | ``` 266 | 267 | 결과는 다음과 같습니다. 268 | 269 | ```javascript 270 | [ 271 | { 272 | id: 4, 273 | text: '배열 내장 함수 배우기', 274 | done: false 275 | } 276 | ]; 277 | ``` 278 | 279 | filter 함수에 넣는 파라미터는 조건을 검사하는 함수를 넣어주며, 이 함수의 파라미터로 각 원소의 값을 받아오게 됩니다. 280 | 281 | 방금 우리가 작성한 코드는 이렇게 입력 할 수도 있습니다. 282 | 283 | ```javascript 284 | const tasksNotDone = todos.filter(todo => !todo.done); 285 | ``` 286 | 287 | filter 에 넣어준 함수에서 true 를 반환하면 새로운 배열에 따로 추출을 해주는데요, 만약 todo.done 값이 false 라면, !false 가 되고 이 값은 true 이기 때문에, 이전의 todo.done === false 와 똑같이 작동하게 됩니다. 288 | 289 | ### splice 290 | 291 | splice 는 배열에서 특정 항목을 제거할 때 사용합니다. 292 | 293 | ```javascript 294 | const numbers = [10, 20, 30, 40]; 295 | ``` 296 | 297 | 위 배열에서 30 을 지운다고 가정해봅시다. 그러면, 30이 몇번째 index 인지 알아낸 이후, 이를 splice 를 통해 지워줄 수 있습니다. 298 | 299 | ```javascript 300 | const numbers = [10, 20, 30, 40]; 301 | const index = numbers.indexOf(30); 302 | numbers.splice(index, 1); 303 | console.log(numbers); 304 | ``` 305 | 306 | 결과는 다음과 같습니다. 307 | 308 | ``` 309 | [10, 20, 40] 310 | ``` 311 | 312 | splice 를 사용 할 때 첫번째 파라미터는 어떤 인덱스부터 지울지를 의미하고 두번째 파라미터는 그 인덱스부터 몇개를 지울지를 의미합니다. 313 | 314 | ### slice 315 | 316 | slice 는 splice 랑 조금 비슷한데요, 배열을 잘라낼 때 사용하는데, 중요한 점은 기존의 배열은 건들이지 않는 다는 것입니다. 317 | 318 | ```javascript 319 | const numbers = [10, 20, 30, 40]; 320 | const sliced = numbers.slice(0, 2); // 0부터 시작해서 2전까지 321 | 322 | console.log(sliced); // [10, 20] 323 | console.log(numbers); // [10, 20, 30, 40] 324 | ``` 325 | 326 | slice 에는 두개의 파라미터를 넣게 되는데 첫번째 파라미터는 어디서부터 자를지, 그리고 두번째 파라미터는 어디까지 자를지 를 의미합니다. 327 | 328 | ### shift 와 pop 329 | 330 | `shift` 와 `pop` 은 비슷하지만, 다릅니다. 331 | 332 | `shift` 는 첫번째 원소를 배열에서 추출해줍니다. (추출하는 과정에서 배열에서 해당 원소는 사라집니다.) 333 | 334 | ```javascript 335 | const numbers = [10, 20, 30, 40]; 336 | const value = numbers.shift(); 337 | console.log(value); 338 | console.log(numbers); 339 | ``` 340 | 341 | 결과는 다음과 같습니다. 342 | 343 | ``` 344 | 10 345 | [20, 30, 40] 346 | ``` 347 | 348 | 이번엔 `pop` 을 해볼까요? 349 | 350 | ```javascript 351 | const numbers = [10, 20, 30, 40]; 352 | const value = numbers.pop(); 353 | console.log(value); 354 | console.log(numbers); 355 | ``` 356 | 357 | 결과는 다음과 같습니다. 358 | 359 | ``` 360 | 40 361 | [10, 20, 30] 362 | ``` 363 | 364 | `pop` 은 `push` 의 반대로 생각하시면 됩니다. `push` 는 배열의 맨 마지막에 새 항목을 추가하고, `pop` 은 맨 마지막 항목을 추출합니다. 365 | 366 | ### unshift 367 | 368 | `unshift` 는 `shift` 의 반대입니다. 369 | 370 | 배열의 맨 앞에 새 원소를 추가합니다. 371 | 372 | ```javascript 373 | const numbers = [10, 20, 30, 40]; 374 | numbers.unshift(5); 375 | console.log(numbers); 376 | ``` 377 | 378 | 결과는 다음과 같습니다. 379 | 380 | ``` 381 | [5, 10, 20, 30, 40] 382 | ``` 383 | 384 | ### concat 385 | 386 | `concat` 은 여러개의 배열을 하나의 배열로 합쳐줍니다. 387 | 388 | ```javascript 389 | const arr1 = [1, 2, 3]; 390 | const arr2 = [4, 5, 6]; 391 | const concated = arr1.concat(arr2); 392 | 393 | console.log(concated); 394 | ``` 395 | 396 | 결과는 다음과 같습니다. 397 | 398 | ```javascript 399 | [1, 2, 3, 4, 5, 6]; 400 | ``` 401 | 402 | `concat` 함수는 arr1 과 arr2 에 변화를 주지 않습니다. 403 | 404 | ### join 405 | 406 | `join` 은 배열 안의 값들을 문자열 형태로 합쳐줍니다. 407 | 408 | ```javascript 409 | const array = [1, 2, 3, 4, 5]; 410 | console.log(array.join()); // 1,2,3,4,5 411 | console.log(array.join(' ')); // 1 2 3 4 5 412 | console.log(array.join(', ')); // 1, 2, 3, 4, 5 413 | ``` 414 | 415 | ### reduce 416 | 417 | `reduce` 함수는 잘 사용 할 줄 알면 정말 유용한 내장 함수입니다. 만약 여러분이 주어진 배열에 대하여 총합을 구해야 하는 상황이 왔다고 가정해봅시다. 418 | 419 | 이렇게 구현을 할 수 있을텐데요 420 | 421 | ```javascript 422 | const numbers = [1, 2, 3, 4, 5]; 423 | 424 | let sum = 0; 425 | numbers.forEach(n => { 426 | sum += n; 427 | }); 428 | console.log(sum); 429 | ``` 430 | 431 | (결과는 15가 됩니다) 432 | 433 | 여기서 sum 을 계산하기 위해서 사전에 sum 을 선언하고, forEach 를 통하여 계속해서 덧셈을 해주었는데요, 434 | 435 | `reduce` 라는 함수를 사용하면 다음과 같이 구현 할 수 있습니다. 436 | 437 | ```javascript 438 | const numbers = [1, 2, 3, 4, 5]; 439 | let sum = array.reduce((accumulator, current) => accumulator + current, 0); 440 | 441 | console.log(sum); 442 | ``` 443 | 444 | reduce 함수에는 두개의 파라미터를 전달합니다. 첫번째 파라미터는 accumulator 와 current 를 파라미터로 가져와서 결과를 반환하는 콜백함수이구요, 두번째 파라미터는 reduce 함수에서 사용 할 초깃값입니다. 445 | 446 | 여기서 accumulator 는 누적된 값을 의미합니다. 447 | 448 | 방금 작성한 함수를 다음과 같이 수정해보세요. 449 | 450 | ```javascript 451 | const numbers = [1, 2, 3, 4, 5]; 452 | let sum = numbers.reduce((accumulator, current) => { 453 | console.log({ accumulator, current }); 454 | return accumulator + current; 455 | }, 0); 456 | 457 | console.log(sum); 458 | ``` 459 | 460 | 이 코드의 실행 결과는 다음과 같습니다. 461 | 462 |  463 | 464 | 배열을 처음부터 끝까지 반복하면서 우리가 전달한 콜백 함수가 호출이 되는데요, 가장 처음엔 accumulator 값이 0 입니다. 이 값이 0인 이유는 우리가 두번째 파라미터인 초깃값으로 0을 설정했기 때문입니다. 465 | 466 | 처음 콜백 함수가 호출되면, 0 + 1 을 해서 1이 반환됩니다. 이렇게 1일 반환되면 그 다음 번에 콜백함수가 호출 될 때 accumulator 값으로 사용됩니다. 467 | 468 | 콜백함수가 두번째로 호출 될 땐 1 + 2 를 해서 3이되고, 이 값이 세번째로 호출될 때의 accumulator 가 됩니다. 469 | 470 | 그래서 쭉- 누적돼서 결과물 15가 나타나는 것 입니다. 471 | 472 | reduce 를 사용해서 평균도 계산 할 수 있습니다. 평균을 계산하려면, 가장 마지막 숫자를 더하고 나서 배열의 length 로 나누어주어야 합니다. 473 | 474 | ```javascript 475 | const numbers = [1, 2, 3, 4, 5]; 476 | let sum = numbers.reduce((accumulator, current, index, array) => { 477 | if (index === array.length - 1) { 478 | return (accumulator + current) / array.length; 479 | } 480 | return accumulator + current; 481 | }, 0); 482 | 483 | console.log(sum); 484 | ``` 485 | 486 | 결과는 3이 됩니다. 487 | 488 | 위 코드의 reduce 에서 사용한 콜백함수에서는 추가 파라미터로 index 와 array 를 받아왔습니다. index 는 현재 처리하고 있는 항목이 몇번째인지 가르키고, array 는 현재 처리하고 있는 배열 자신을 의미합니다. 489 | 490 | ### 퀴즈 491 | 492 | 이제 지금까지 배운 것들을 활용하여 퀴즈를 풀어봅시다! 493 | 494 | 숫자 배열이 주어졌을 때 10보다 큰 숫자의 갯수를 반환하는 함수를 만드세요. 495 | 496 | ```javascript 497 | function countBiggerThanTen(numbers) { 498 | /* 구현해보세요 */ 499 | } 500 | 501 | const count = countBiggerThanTen([1, 2, 3, 5, 10, 20, 30, 40, 50, 60]); 502 | console.log(count); // 5 503 | ``` 504 | 505 | [](https://codesandbox.io/s/j33q4wm9z5?fontsize=14) 506 | 507 | 위 버튼을 클릭하여 코드를 작성해서 Test를 통과시키세요. 508 | 509 | 이 문제는 우리가 배운 내장 함수들 중에서 여러 종류를 사용하여 다른 방식으로 구현 할 수 있습니다. 510 | 511 | - [정답1](https://codesandbox.io/s/5w3971pkzp) 512 | - [정답2](https://codesandbox.io/s/zkzoqv298l) 513 | - [정답3](https://codesandbox.io/s/v3rl89wv8y) 514 | -------------------------------------------------------------------------------- /basics/10-prototype-class.md: -------------------------------------------------------------------------------- 1 | ## 10. 프로토타입과 클래스 2 | 3 | ### 객체 생성자 4 | 5 | 프로토타입과 클래스에 대해서 알아보기 전에 우선 객체 생성자라는 것을 알아봅시다. 객체 생성자는 함수를 통해서 새로운 객체를 만들고 그 안에 넣고 싶은 값 혹은 함수들을 구현 할 수 있게 해줍니다. 6 | 7 | 다음 코드를 입력해보세요. 8 | 9 | ```javascript 10 | function Animal(type, name, sound) { 11 | this.type = type; 12 | this.name = name; 13 | this.sound = sound; 14 | this.say = function() { 15 | console.log(this.sound); 16 | }; 17 | } 18 | 19 | const dog = new Animal('개', '멍멍이', '멍멍'); 20 | const cat = new Animal('고양이', '야옹이', '야옹'); 21 | 22 | dog.say(); 23 | cat.say(); 24 | ``` 25 | 26 | 결과물은 다음과 같습니다. 27 | 28 | ``` 29 | 멍멍 30 | 야옹 31 | ``` 32 | 33 | 객체 생성자를 사용 할 때는 보통 함수의 이름을 대문자로 시작하고, 새로운 객체를 만들 때에는 `new` 키워드를 앞에 붙여주어야 합니다. 34 | 35 | 지금 위 코드를 보시면, dog 가 가지고 있는 say 함수와 cat 이 가지고 있는 수행하는 코드가 똑같음에도 불구하고 객체가 생성 될 때 마다 함수도 새로 만들어져서 this.say 로 설정이 되고 있습니다. 36 | 37 | 같은 객체 생성자 함수를 사용하는 경우, 특정 함수 또는 값을 재사용 할 수 있는데 바로 프로토타입입니다. 38 | 39 | ### 프로토타입 40 | 41 | 프로토타입은 다음과 같이 객체 생성자 함수 아래에 `.prototype.[원하는키] =` 코드를 입력하여 설정 할 수 있습니다. 42 | 43 | ```javascript 44 | function Animal(type, name, sound) { 45 | this.type = type; 46 | this.name = name; 47 | this.sound = sound; 48 | } 49 | 50 | Animal.prototype.say = function() { 51 | console.log(this.sound); 52 | }; 53 | Animal.prototype.sharedValue = 1; 54 | 55 | const dog = new Animal('개', '멍멍이', '멍멍'); 56 | const cat = new Animal('고양이', '야옹이', '야옹'); 57 | 58 | dog.say(); 59 | cat.say(); 60 | 61 | console.log(dog.sharedValue); 62 | console.log(cat.sharedValue); 63 | ``` 64 | 65 | 결과는 다음과 같습니다. 66 | 67 | ``` 68 | 멍멍 69 | 야옹 70 | 1 71 | 1 72 | ``` 73 | 74 | ### 객체 생성자 상속받기 75 | 76 | 예를 들어서 우리가 Cat 과 Dog 라는 새로운 객체 생성자를 만든다고 가정해봅시다. 그리고, 해당 객체 생성자들에서 Animal 의 기능을 재사용한다고 가정해봅시다. 그렇다면, 이렇게 구현 할 수 있습니다. 77 | 78 | ```javascript 79 | function Animal(type, name, sound) { 80 | this.type = type; 81 | this.name = name; 82 | this.sound = sound; 83 | } 84 | 85 | Animal.prototype.say = function() { 86 | console.log(this.sound); 87 | }; 88 | Animal.prototype.sharedValue = 1; 89 | 90 | function Dog(name, sound) { 91 | Animal.call(this, '개', name, sound); 92 | } 93 | Dog.prototype = Animal.prototype; 94 | 95 | function Cat(name, sound) { 96 | Animal.call(this, '고양이', name, sound); 97 | } 98 | Cat.prototype = Animal.prototype; 99 | 100 | const dog = new Dog('멍멍이', '멍멍'); 101 | const cat = new Cat('야옹이', '야옹'); 102 | 103 | dog.say(); 104 | cat.say(); 105 | ``` 106 | 107 | 새로 만든 Dog 와 Cat 함수에서 `Animal.call` 을 호출해주고 있는데요, 여기서 첫번째 인자에는 this 를 넣어주어야 하고, 그 이후에는 Animal 객체 생성자 함수에서 필요로 하는 파라미터를 넣어주어야 합니다. 108 | 109 | 추가적으로 prototype 을 공유해야 하기 때문에 상속받은 객체 생성자 함수를 만들고 나서 prototype 값을 Animal.prototype 으로 설정해주었습니다. 110 | 111 | ### 클래스 112 | 113 | 클래스라는 기능은 C++, Java, C#, PHP 등의 다른 프로그래밍 언어에는 있는 기능인데 자바스크립트에는 없었기 때문에 예전 자바스크립트 (ES5) 에서는 클래스 문법이 따로 없었기 때문에 위에서 작성한 코드처럼 객체 생성자 함수를 사용하여 비슷한 작업을 구현해왔습니다. 114 | 115 | ES6 에서부터는 `class` 라는 문법이 추가되었는데요, 우리가 객체 생성자로 구현했던 코드를 조금 더 명확하고, 깔끔하게 구현 할 수 있게 해줍니다. 추가적으로, 상속도 훨씬 쉽게 해줄 수 있습니다. 116 | 117 | ```javascript 118 | class Animal { 119 | constructor(type, name, sound) { 120 | this.type = type; 121 | this.name = name; 122 | this.sound = sound; 123 | } 124 | say() { 125 | console.log(this.sound); 126 | } 127 | } 128 | 129 | const dog = new Animal('개', '멍멍이', '멍멍'); 130 | const cat = new Animal('고양이', '야옹이', '야옹'); 131 | 132 | dog.say(); 133 | cat.say(); 134 | ``` 135 | 136 | 여기서 우리가 say 라는 함수를 클래스 내부에 선언하였는데요, 클래스 내부의 함수를 '메서드'라고 부릅니다. 이렇게 메서드를 만들면 자동으로 prototype 으로 등록이 됩니다. 137 | 138 | 결과는 다음과 같습니다. 139 | 140 | ``` 141 | 멍멍 142 | 야옹 143 | ``` 144 | 145 | 146 | 147 | `class` 를 사용했을때에는, 다른 클래스를 쉽게 상속 할 수 있습니다. 148 | 149 | ```javascript 150 | class Animal { 151 | constructor(type, name, sound) { 152 | this.type = type; 153 | this.name = name; 154 | this.sound = sound; 155 | } 156 | say() { 157 | console.log(this.sound); 158 | } 159 | } 160 | 161 | class Dog extends Animal { 162 | constructor(name, sound) { 163 | super('개', name, sound); 164 | } 165 | } 166 | 167 | class Cat extends Animal { 168 | constructor(name, sound) { 169 | super('고양이', name, sound); 170 | } 171 | } 172 | 173 | const dog = new Dog('멍멍이', '멍멍'); 174 | const cat = new Cat('야옹이', '야옹'); 175 | 176 | dog.say(); 177 | cat.say(); 178 | ``` 179 | 180 | 결과물은 다음과 같습니다. 181 | 182 | ``` 183 | 멍멍 184 | 야옹 185 | ``` 186 | 187 | 상속을 할 때는 `extends` 키워드를 사용하며, constructor에서 사용하는 `super()` 함수가 상속받은 클래스의 생성자를 가르킵니다. 188 | 189 | ```javascript 190 | class Animal { 191 | constructor(type, name, sound) { 192 | this.type = type; 193 | this.name = name; 194 | this.sound = sound; 195 | } 196 | } 197 | 198 | class Dog extends Animal { 199 | constructor(name, sound) { 200 | super('개', name, sound); 201 | } 202 | } 203 | 204 | class Cat extends Animal { 205 | constructor(name, sound) { 206 | super('고양이', name, sound); 207 | } 208 | } 209 | 210 | const dog = new Dog('멍멍이', '멍멍'); 211 | const dog2 = new Dog('왈왈이', '왈왈'); 212 | const cat = new Cat('야옹이', '야옹'); 213 | const cat2 = new Cat('냐옹이', '냐옹'); 214 | 215 | dog.say(); 216 | dog2.say(); 217 | cat.say(); 218 | cat2.say(); 219 | ``` 220 | 221 | 222 | ### 연습 223 | 224 | 연습삼아 다음 클래스도 만들어보세요. 225 | 226 | ```javascript 227 | class Food { 228 | constructor(name) { 229 | this.name = name; 230 | this.brands = []; 231 | } 232 | addBrand(brand) { 233 | this.brands.push(brand) 234 | } 235 | print() { 236 | console.log(`${this.name}을/를 파는 음식점들:`) 237 | console.log(this.brands.join(', ')); 238 | } 239 | } 240 | 241 | const pizza = new Food('피자'); 242 | pizza.addBrand('피자헛'); 243 | pizza.addBrand('도미노 피자'); 244 | 245 | const chicken = new Food('치킨'); 246 | chicken.addBrand('굽네치킨'); 247 | chicken.addBrand('BBQ'); 248 | 249 | pizza.print() 250 | chicken.print(); 251 | ``` 252 | 253 | 이런식으로, 클래스를 만들어서 사용하면 같은 형태를 지닌 객체들을 만들때 객체들이 지닌 값과 함수를 보기 좋은 형태로 쉽게 관리 할 수 있습니다. -------------------------------------------------------------------------------- /basics/README.md: -------------------------------------------------------------------------------- 1 | # 자바스크립트 입문 2 | 3 | 자바스크립트를 기초부터 배워봅시다! 4 | 5 | ## JavaScript 는 뭔가요? 6 | 7 | JavaScript 는 웹 브라우저에서 사용하기 위하여 만들어진 프로그래밍 언어입니다. 이 언어는 90년대부터 주로 웹 브라우저 상에서 UI 를 동적으로 보여주기 위하여 사용을 해왔습니다. 기존에는 브라우저에서만 사용해왔던 언어인데, 이제는 단순히 웹페이지에서만 국한되지 않고 Node.js 런타임을 통하여 서버 쪽에서도 사용을 할 수 있게 되었습니다. 8 | 9 | 추가적으로, NW.js, Electron 등의 도구를 사용하여 데스크탑 앱을 만들 수도 있고, react-native, NativeScript 등의 도구를 사용하여 모바일 앱도 만들 수 있습니다. 10 | 11 | 그리고 하드웨어에서도 Node.js 를 통하여 JavaScript 를 사용 할 수 있기 때문에 IoT 진영에서도 사용 될 수도 있죠. 12 | 13 | JavaScript 는 나날히 발전해 가고 있고, 매년마다 새로운 문법들도 나오고 있습니다. 이 강의에서는 모든 문법들을 다루지는 않습니다. 하지만, 알아두면 개발하는데 충분히 쓸모있는 만큼 학습하게 됩니다. 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["collapsible-chapters", "comment", "hide-published-with", "github", "edit-link"], 3 | "pluginsConfig": { 4 | "collapsible-chapters":{}, 5 | "github": { 6 | "url": "https://github.com/velopert/learnjs" 7 | }, 8 | "edit-link": { 9 | "base": "https://github.com/velopert/learnjs/edit/master", 10 | "label": "수정 요청하기" 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /gitbook-plugin-comment/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | hooks: { 3 | 'page:before': function (page) { 4 | var str = ""; 5 | page.content = page.content + str; 6 | return page; 7 | } 8 | } 9 | } -------------------------------------------------------------------------------- /gitbook-plugin-comment/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Customize the footer of each article, you can add copyright and document reversion of time", 3 | "devDependencies": {}, 4 | "directories": {}, 5 | "engines": { 6 | "gitbook": ">=3.2.2" 7 | }, 8 | "license": "MIT", 9 | "main": "index.js", 10 | "name": "gitbook-plugin-comment", 11 | "optionalDependencies": {}, 12 | "readme": "ERROR: No README data found!", 13 | "version": "1.0.5" 14 | } 15 | -------------------------------------------------------------------------------- /html/01-counter.md: -------------------------------------------------------------------------------- 1 | ## 01. 카운터 2 | 3 | 4 | 첫번째로 만들어볼것은, 버튼을 클릭하면 숫자가 올라가거나 내려가는 카운터입니다. CodeSandbox 에서 새로운 Vanilla 샌드박스를 만들고, index.js 파일 내용은 비우고, index.html 을 다음과 같이 수정해보세요. 5 | 6 | ### UI 만들기 7 | 8 | 9 | ```html 10 | 11 | 12 |
13 |내용내용내용
26 | 27 | 28 | 29 | 30 | ``` 31 | 32 | 33 |  34 | 35 | 이렇게 화면이 나타났나요? 36 | 37 | 그 다음엔, 버튼 아래에 다음 내용을 보여주세요. 38 | 39 | ```html 40 | 41 | 42 | 43 |내용내용내용
50 | 51 |모달 내용은 어쩌고 저쩌고..
55 |내용내용내용
130 | 131 | 140 | 141 | 142 | 143 | ``` 144 | 145 | `display: none;` 스타일을 사용하게 되면 해당 엘리먼트는 화면에서 숨겨지게됩니다. 146 | 147 | 148 | 이제, index.js 를 열어서 버튼과 모달의 DOM 을 선택해주고, 클릭 이벤트를 설정해주세요 149 | 150 | ```javascript 151 | import "./styles.css"; 152 | 153 | const open = document.getElementById("open"); 154 | const close = document.getElementById("close"); 155 | const modal = document.querySelector(".modal-wrapper"); 156 | open.onclick = () => { 157 | modal.style.display = "flex"; 158 | }; 159 | close.onclick = () => { 160 | modal.style.display = "none"; 161 | }; 162 | ``` 163 | 164 | `id` 가 아닌 클래스로 DOM을 선택하고 싶을땐 `document.getElementsByClassName` 또는 `document.querySelector` 를 사용하면 됩니다. `document.querySelector` 를 사용하여 class 값으로 DOM 을 선택 할 때에는 텍스트 앞에 `.` 을 붙여주어야 합니다. 165 | 166 | 167 | 이제 버튼들을 눌러보세요. 잘 작동하나요? 168 | 169 |  170 | 171 | [](https://codesandbox.io/s/vigorous-shadow-dx22s?fontsize=14) 172 | 173 | -------------------------------------------------------------------------------- /html/README.md: -------------------------------------------------------------------------------- 1 | # 4장. HTML 과 JavaScript 연동하기 2 | 3 | HTML 을 사용하면 브라우저에서 우리가 보여주고 싶은 UI (유저 인터페이스) 를 보여줄 수 있습니다. 만약에 사용자의 인터랙션 (상호작용) 에 따라 동적으로 UI 를 업데이트하고 싶다면, JavaScript 를 연동해주어야 합니다. 4 | 5 | 보통 인터랙션이 많은 경우에는 Vanilla JavaScript (별도의 라이브러리/프레임워크를 사용하지 않는 형태) 를 사용해서 하기에는 코드의 양도 많아지고 코드 관리도 어려운 편이라 보통 React, Vue, Angular 등의 도구를 사용합니다. 6 | 7 | 그래도, 해당 도구 없이 하는 기본적인 방법 또한 이해를 해둬야 앞으로 라이브러리/프레임워크를 공부하게 될 때 이해에 도움을 주므로, 간단한 예제 몇가지를 함께 만들어보겠습니다. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "gitbook-plugin-expandable-chapters": "^0.2.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /reference.md: -------------------------------------------------------------------------------- 1 | ## 참고 문헌 2 | 3 | - https://codeburst.io/cool-javascript-shortcuts-and-tips-for-everyday-use-66cd174ab216 4 | - https://www.sitepoint.com/shorthand-javascript-techniques/ 5 | - https://medium.com/@kavisha.talsania/top-10-es6-features-every-javascript-developer-must-know-4c81ec54bbcd 6 | - https://webapplog.com/es6/ 7 | - https://hackernoon.com/understanding-javascript-scope-1d4a74adcdf5 8 | -------------------------------------------------------------------------------- /useful/01-ternary.md: -------------------------------------------------------------------------------- 1 | ## 01. 삼항 연산자 2 | 3 | 첫번째로 배울 문법은, 삼항 연산자입니다. 이 문법은 ES6 문법은 아닙니다. 4 | 5 | ```javascript 6 | const array = []; 7 | let text = ''; 8 | if (array.length === 0) { 9 | text = '배열이 비어있습니다.'; 10 | } else { 11 | text = '배열이 비어있지 않습니다.'; 12 | } 13 | console.log(text); 14 | ``` 15 | 16 | 예를 들어 위와 같이 특정 조건에 따라 text 값이 달라야 하는 상황이 있다고 가정해봅시다. 17 | 18 | 그런 경우에는 다음과 같이 코드를 작성 할 수 있습니다. 19 | 20 | ```javascript 21 | const array = []; 22 | let text = array.length === 0 ? '배열이 비어있습니다' : '배열이 비어있지 않습니다.'; 23 | 24 | console.log(text); 25 | ``` 26 | 27 | 삼항 연산자의 사용법은 다음과 같습니다. 28 | 29 | ```javascript 30 | 조건 ? true일때 : false일때 31 | ``` 32 | 33 | 라인의 길이가 너묵 길어진다면 다음과 같이 작성하기도 합니다. 34 | 35 | ```javascript 36 | const array = []; 37 | let text = array.length === 0 38 | ? '배열이 비어있습니다' 39 | : '배열이 비어있지 않습니다.'; 40 | 41 | console.log(text); 42 | ``` 43 | 44 | 다음과 같이 삼항 연산자를 중첩해서 쓸 수도 있는데요 45 | 46 | ```javascript 47 | const condition1 = false; 48 | const condition2 = false; 49 | 50 | const value = condition1 51 | ? '와우!' 52 | : condition2 53 | ? 'blabla' 54 | : 'foo'; 55 | 56 | console.log(value); 57 | ``` 58 | 59 | 가독성이 그렇게 좋지 않으니 이러한 코드는 피하시는 것이 좋습니다. 이런 상황에는 차라리 if문으로 처리하는게 오히려 코드를 읽기가 쉬워질 수도 있습니다. 60 | -------------------------------------------------------------------------------- /useful/02-truthy-and-falsy.md: -------------------------------------------------------------------------------- 1 | ## 02. Truthy and Falsy 2 | 3 | 이것은 자바스크립트 문법까지는 아니지만, 알아둬야 하는 개념입니다. 4 | 5 | Truthy: true 같은거... 6 | Falsy: false 같은거... 7 | 8 | 라고 이해를 하면 되는데요, 예를 들어서 다음과 같은 함수가 있다고 가정해봅시다. 9 | 10 | ```javascript 11 | function print(person) { 12 | console.log(person.name); 13 | } 14 | 15 | const person = { 16 | name: 'John' 17 | }; 18 | 19 | print(person); 20 | ``` 21 | 22 | 만약에 이러한 상황에서, 만약 print 함수가 다음과 같이 파라미터가 비어진 채로 실행됐다고 가정해봅시다. 23 | 24 | ```javascript 25 | function print(person) { 26 | console.log(person.name); 27 | } 28 | 29 | const person = { 30 | name: 'John' 31 | }; 32 | 33 | print(); 34 | ``` 35 | 36 | 이 코드는 다음과 같은 에러를 생성해냅니다. 37 | 38 | ``` 39 | TypeError: Cannot read property 'name' of undefined 40 | ``` 41 | 42 | 이러한 상황에서, 만약에 print 함수에서 만약에 object 가 주어지지 않았다면, 문제가 있다고 콘솔에 출력해야 한다면 다음과 같이 구현 할 수 있습니다. 43 | 44 | ```javascript 45 | function print(person) { 46 | if (person === undefined) { 47 | return; 48 | } 49 | console.log(person.name); 50 | } 51 | 52 | const person = { 53 | name: 'John' 54 | }; 55 | 56 | print(); 57 | ``` 58 | 59 | 그런데 만약에 다음과 같이 print 에 null 값이 파라미터로 전달되면 어떨까요? 60 | 61 | ```javascript 62 | function print(person) { 63 | if (person === undefined) { 64 | console.log('person이 없네요'); 65 | return; 66 | } 67 | console.log(person.name); 68 | } 69 | 70 | const person = null; 71 | print(person); 72 | ``` 73 | 74 | 그러면 또 오류가 발생하게 됩니다. 75 | 76 | ``` 77 | TypeError: Cannot read property 'name' of null 78 | ``` 79 | 80 | 81 | 그러면 또.. print 함수에 조건을 추가해줘야합니다. 82 | 83 | ```javascript 84 | function print(person) { 85 | if (person === undefined || person === null) { 86 | console.log('person이 없네요'); 87 | return; 88 | } 89 | console.log(person.name); 90 | } 91 | 92 | const person = null; 93 | print(person); 94 | ``` 95 | 96 | 97 | 이렇게 person 이 undefined 이거나, null 인 상황을 대비하려면 위와 같이 코드를 작성해야하는데요, 여기서 위 코드는 다음과 같이 축약해서 작성 할 수 있답니다. 98 | 99 | ```javascript 100 | function print(person) { 101 | if (!person) { 102 | console.log('person이 없네요'); 103 | return; 104 | } 105 | console.log(person.name); 106 | } 107 | 108 | const person = null; 109 | print(person); 110 | ``` 111 | 112 | 이게 작동하는 이유는, undefined 와 null 은 Falsy 한 값입니다. Falsy 한 값 앞에 느낌표를 붙여주면 true 로전환됩니다. 113 | 114 | 다음 코드를 입력해보세요. 115 | 116 | ```javascript 117 | console.log(!undefined); 118 | console.log(!null); 119 | ``` 120 | 121 | Falsy 한 값은 이 외에도 몇개 더 있습니다. 122 | 123 | ```javascript 124 | console.log(!undefined); 125 | console.log(!null); 126 | console.log(!0); 127 | console.log(!''); 128 | console.log(!NaN); 129 | ``` 130 | 131 | 이 값은 모두 true 가 됩니다. 132 | 133 | 여기서 NaN 이란 값은 조금 생소하지요, 이 값은 Not A Number 라는 의미를 가지고 있는데요, 보통 NaN 은 문자열을 숫자로 변환하는 자바스크립트 기본함수 parseInt 라는 함수를 사용하게 될 때 볼 수 있습니다. 134 | 135 | ```javascript 136 | const num = parseInt('15', 10); // 10진수 15를 숫자로 변환하겠다는 의미 137 | console.log(num); // 10 138 | const notnum = parseInt('야호~', 10); 139 | console.log(notnum); // NaN 140 | ``` 141 | 142 | 다시 본론으로 돌아와서, Falsy 한 값은 아까 나열한 다섯가지 입니다. 143 | 144 | 그리고, 그 외의 값은 모두! Truthy 한 값입니다. 145 | 146 | 147 | 한번, 이렇게 코드를 적어보세요. 148 | 149 | ```javascript 150 | console.log(!3); 151 | console.log(!'hello'); 152 | console.log(!['array?']); 153 | console.log(![]); 154 | console.log(!{ value: 1 }); 155 | ``` 156 | 157 | 이번에는 아까와는 반대로 모든 값이 false 가 됩니다. 158 | 159 | 160 | Truthy 한 값과 Falsy 한 값은 if 문에서도 사용 할 수있습니다. 161 | 162 | ```javascript 163 | const value = { a: 1 }; 164 | if (value) { 165 | console.log('value 가 Truthy 하네요.'); 166 | } 167 | ``` 168 | 169 | value 가 Truthy 한 값이기 때문에, 콘솔에 메시지가 출력 될 것입니다. 반면, value 가 null, undefined, 0, '', NaN 중 하나라면, 나타나지 않을 것입니다. 170 | 171 | 172 | 그래서 이렇게, Truthy 한 값과 Falsy 한 값을 잘 알아놓으면 조건문을 작성할 때 편할 것입니다. 173 | 174 | 175 | 추가적으로, 알아두면 유용한 팁 하나를 드리겠습니다. 176 | 177 | 만약에, 특정 값이 Truthy 한 값이라면 true, 그렇지 않다면 false 로 값을 표현하는 것을 구현해보겠습니다. 178 | 179 | ```javascript 180 | const value = { a: 1 }; 181 | 182 | const truthy = value ? true : false; 183 | ``` 184 | 185 | 우리가 이전에 배운 삼항연산자를 사용하면 쉽게 value 값의 존재 유무에 따라 쉽게 true 및 false 로 전환이 가능합니다. 그런데, 이를 더 쉽게 할 수도 있습니다. 186 | 187 | ```javascript 188 | const value = { a: 1 }; 189 | const truthy = !!value; 190 | ``` 191 | 192 | !value 는 false 가 되고, 여기에 !false 는 true 가 되어서, 결과는 true 가 됩니다. -------------------------------------------------------------------------------- /useful/03-short-circuiting.md: -------------------------------------------------------------------------------- 1 | ## 03. 단축 평가 (short-circuit evaluation) 논리 계산법 2 | 3 | 이번에는 논리 연산자를 조금 더 유용하게 사용하는 방법에 대해서 배워보겠습니다. 4 | 5 | 우리가 이전에 연산자를 배울때, 다음과 사항을 잘 숙지하셨을겁니다. 6 | 7 | ```javascript 8 | true && true // true 9 | true && false // false 10 | true || false // true 11 | false || true // true 12 | ``` 13 | 14 | 논리 연산자를 사용 할 때에는 무조건 우리가 true 혹은 false 값을 사용해야 되는 것은 아닙니다. 문자열이나 숫자, 객체를 사용 할 수도 있고, 해당 값이 Truthy 하냐 Falsy 하냐에 따라 결과가 달라집니다. 15 | 16 | 예를 들어서 다음과 같은 코드가 있다고 가정해보겠습니다. 17 | 18 | ```javascript 19 | const dog = { 20 | name: '멍멍이' 21 | }; 22 | 23 | function getName(animal) { 24 | return animal.name; 25 | } 26 | 27 | const name = getName(dog); 28 | console.log(name); // 멍멍이 29 | ``` 30 | 31 | 그런데 만약, getName 의 파라미터에 제대로된 객체가 주어지지 않으면 어떻게 될까요? 32 | 33 | ```javascript 34 | const dog = { 35 | name: '멍멍이' 36 | }; 37 | 38 | function getName(animal) { 39 | return animal.name; 40 | } 41 | 42 | const name = getName(); 43 | console.log(name); 44 | ``` 45 | 46 |  47 | 48 | animal 객체가 undefined 이기 때문에, undefined 에서 name 값을 조회 할 수 없어서 이렇게 에러가 발생하게 됩니다. 49 | 50 | 그렇다면, 만약 함수에서 animal 값이 제대로 주어졌을 때만 name 을 조회하고, 그렇지 않을때는 그냥 undefined 를 반환하게 하고 싶으면 어떻게 해야 할까요? 51 | 52 | ```javascript 53 | const dog = { 54 | name: '멍멍이' 55 | }; 56 | 57 | function getName(animal) { 58 | if (animal) { 59 | return animal.name; 60 | } 61 | return undefined; 62 | } 63 | 64 | const name = getName(); 65 | console.log(name); 66 | ``` 67 | 68 | 이렇게 하면 animal 값이 주어지지 않아도, 에러가 발생하지 않게 됩니다. 이러한 코드를 논리 연산자를 사용하면 코드를 단축시킬 수 있습니다. 69 | 70 | ### && 연산자로 코드 단축시키기 71 | 72 | 이렇게 코드를 작성해보세요. 73 | 74 | ```javascript 75 | const dog = { 76 | name: '멍멍이' 77 | }; 78 | 79 | function getName(animal) { 80 | return animal && animal.name; 81 | } 82 | 83 | const name = getName(); 84 | console.log(name); // undefined 85 | ``` 86 | 87 | 아까 코드와 이 코드는 완벽히 똑같이 작동하는 코드입니다. 한번 다음과 같이 파라미터를 넣어서 호출도 해보세요. 88 | 89 | ```javascript 90 | const dog = { 91 | name: '멍멍이' 92 | }; 93 | 94 | function getName(animal) { 95 | return animal && animal.name; 96 | } 97 | 98 | const name = getName(dog); 99 | console.log(name); // 멍멍이 100 | ``` 101 | 102 | 이게 작동하는 이유는, A && B 연산자를 사용하게 될 때에는 A 가 Truthy 한 값이라면, B 가 결과값이 됩니다. 반면, A 가 Falsy 한 값이라면 결과는 A 가 됩니다. 103 | 104 | 105 | 다음 예시를 한번 살펴보세요. 106 | 107 | ```javascript 108 | console.log(true && 'hello'); // hello 109 | console.log(false && 'hello'); // false 110 | console.log('hello' && 'bye'); // bye 111 | console.log(null && 'hello'); // null 112 | console.log(undefined && 'hello'); // undefined 113 | console.log('' && 'hello'); // '' 114 | console.log(0 && 'hello'); // 0 115 | console.log(1 && 'hello'); // hello 116 | console.log(1 && 1); // 1 117 | ``` 118 | 119 | 이러한 속성을 잘 알아두면, 특정 값이 유효할때에만 어떤 값을 조회하는 작업을 해야 할 때 매우 유용합니다. 120 | 121 | 122 | ### || 연산자로 코드 단축시키기 123 | 124 | || 연산자는 만약 어떤 값이 Falsy 하다면 대체로 사용 할 값을 지정해줄 때 매우 유용하게 사용 할 수 있습니다. 125 | 126 | 예를 들어서 다음과 같은 코드가 있다고 가정해봅시다. 127 | 128 | ```javascript 129 | const namelessDog = { 130 | name: '' 131 | }; 132 | 133 | function getName(animal) { 134 | const name = animal && animal.name; 135 | if (!name) { 136 | return '이름이 없는 동물입니다'; 137 | } 138 | return name; 139 | } 140 | 141 | const name = getName(namelessDog); 142 | console.log(name); // 이름이 없는 동물입니다. 143 | ``` 144 | 145 | 위 코드는 || 연산자를 사용하면 다음과 같이 단축시킬 수 있습니다. 146 | 147 | ```javascript 148 | const namelessDog = { 149 | name: '' 150 | }; 151 | 152 | function getName(animal) { 153 | const name = animal && animal.name; 154 | return name || '이름이 없는 동물입니다.'; 155 | } 156 | 157 | const name = getName(namelessDog); 158 | console.log(name); // 이름이 없는 동물입니다. 159 | ``` 160 | 161 | A || B 는 만약 A 가 Truthy 할경우 결과는 A 가 됩니다. 반면, A 가 Falsy 하다면 결과는 B 가 됩니다. 162 | 163 | -------------------------------------------------------------------------------- /useful/04-default-function-params.md: -------------------------------------------------------------------------------- 1 | ## 04. 함수의 기본 파라미터 2 | 3 | 이번에는 함수의 기본 파라미터를 설정하는 방법에 대해서 알아보겠습니다. 4 | 5 | 한번, 우리가 원의 넓이를 구하는 함수를 만들어보겠습니다. 6 | 7 | ```javascript 8 | function calculateCircleArea(r) { 9 | return Math.PI * r * r; 10 | } 11 | 12 | const area = calculateCircleArea(4); 13 | console.log(area); // 50.26548245743669 14 | ``` 15 | 16 | 여기서 Math.PI 는 원주율 파이(π) 값을 가르킵니다. 17 | 18 | 만약 우리가 이 함수에 r 값을 넣어주지 않으면 어떤 결과가 나타날까요? 19 | 20 | ```javascript 21 | function calculateCircleArea(r) { 22 | return Math.PI * r * r; 23 | } 24 | 25 | const area = calculateCircleArea(); 26 | console.log(area); // NaN 27 | ``` 28 | 29 | 결과는 NaN 이 나옵니다. Not a Number 라는 의미로, 우리가 undefined * undefined 이렇게 숫자가 아닌 값에 곱셈을 하니까 이상한 결과물이 나와버렸습니다. 30 | 31 | 이 함수에서 만약에 r 값이 주어지지 않았다면 기본 값을 1을 사용하도록 설정해봅시다. 32 | 33 | 우리가 지금까지 배운 것들을 활용하면 이렇게 작성 할 수 있습니다. 34 | 35 | ```javascript 36 | function calculateCircleArea(r) { 37 | const radius = r || 1; 38 | return Math.PI * radius * radius; 39 | } 40 | 41 | const area = calculateCircleArea(); 42 | console.log(area); // 3.141592653589793 43 | ``` 44 | 45 | ES5 시절엔 위와 같이 하는게 최선이였는데, ES6 에선 다음과 같이 할 수 있게 되었습니다. 46 | 47 | ```javascript 48 | function calculateCircleArea(r = 1) { 49 | return Math.PI * r * r; 50 | } 51 | 52 | const area = calculateCircleArea(); 53 | console.log(area); // 3.141592653589793 54 | ``` 55 | 56 | 훨씬 깔끔하죠? 57 | 58 | 함수의 기본 파라미터 문법은 화살표 함수에서도 사용 할 수 있습니다. 59 | 60 | ```javascript 61 | const calculateCircleArea = (r = 1) => Math.PI * r * r; 62 | 63 | const area = calculateCircleArea(); 64 | console.log(area); // 3.141592653589793 65 | ``` 66 | 67 | -------------------------------------------------------------------------------- /useful/05-smarter-conditions.md: -------------------------------------------------------------------------------- 1 | ## 05. 조건문 더 스마트하게 쓰기 2 | 3 | 이번에는 조건문을 조금 더 스마트하게 쓰는 방법에 대해서 알아보겠습니다. 4 | 5 | ### 특정 값이 여러 값중 하나인지 확인해야 할 때 6 | 7 | 만약, 여러분이 특정 값이 여러 값 중 하나인지 확인을 해야 하는 상황이 생겼다고 해봅시다. 8 | 9 | 그러면, 이러한 시도를 할 수도 있을 것입니다. 10 | 11 | ```javascript 12 | function isAnimal(text) { 13 | return ( 14 | text === '고양이' || text === '개' || text === '거북이' || text === '너구리' 15 | ); 16 | } 17 | 18 | console.log(isAnimal('개')); // true 19 | console.log(isAnimal('노트북')); // false 20 | ``` 21 | 22 | 비교해야 할 값이 많아질 수록 코드는 길어집니다. 23 | 24 | 이러한 코드를 간단하게 해결 할 수 있는방법은, 배열을 만들고 배열의 includes 함수를 사용하는 것 입니다. 25 | 26 | 27 | ```javascript 28 | function isAnimal(name) { 29 | const animals = ['고양이', '개', '거북이', '너구리']; 30 | return animals.includes(name); 31 | } 32 | 33 | console.log(isAnimal('개')); // true 34 | console.log(isAnimal('노트북')); // false 35 | ``` 36 | 37 | 어떤가요? 훨씬 깔끔하죠? 38 | 39 | 40 | 원한다면, animals 배열을 선언하는 것도 생략하고, 화살표 함수로 작성할 수도 있습니다. 41 | 42 | ```javascript 43 | const isAnimal = name => ['고양이', '개', '거북이', '너구리'].includes(name); 44 | 45 | console.log(isAnimal('개')); // true 46 | console.log(isAnimal('노트북')); // false 47 | ``` 48 | 49 | 물론, 코드가 짧다고 해서 무조건 좋은것은 아닙니다. 단, 코드가 짧으면서도 읽었을 때 어떤 역할을 하는지 잘 이해가 될 수 있어야 비로소 좋은 코드 입니다. 50 | 51 | 52 | ### 값에 따라 다른 결과물을 반환 해야 할 때 53 | 54 | 이번에는 주어진 값에 따라 다른 결과물을 반환해야 할 때 사용 할 수 있는 유용한 팁을 알아보겠습니다. 55 | 56 | 예를 들어서, 동물 이름을 받아오면, 동물의 소리를 반환하는 함수를 만들고 싶다고 가정해보겠습니다. 57 | 58 | ```javascript 59 | function getSound(animal) { 60 | if (animal === '개') return '멍멍!'; 61 | if (animal === '고양이') return '야옹~'; 62 | if (animal === '참새') return '짹짹'; 63 | if (animal === '비둘기') return '구구 구 구'; 64 | return '...?'; 65 | } 66 | 67 | console.log(getSound('개')); // 멍멍! 68 | console.log(getSound('비둘기')); // 구구 구 구 69 | ``` 70 | 71 | > if 문의 코드 블록이 한줄짜리라면 { } 를 생략 할 수도 있습니다. 72 | 73 | 만약 여기서 우리가 배운 switch case 문을 사용하여 다음과 같이 구현 할 수도 있습니다. 74 | 75 | ```javascript 76 | function getSound(animal) { 77 | switch (animal) { 78 | case '개': 79 | return '멍멍!'; 80 | case '고양이': 81 | return '야옹~'; 82 | case '참새': 83 | return '짹짹'; 84 | case '비둘기': 85 | return '구구 구 구'; 86 | default: 87 | return '...?'; 88 | } 89 | } 90 | 91 | console.log(getSound('개')); // 멍멍! 92 | console.log(getSound('비둘기')); // 구구 구 구 93 | ``` 94 | 95 | 참고로 switch 문에서 return 을 할 때에는 break 를 생략해도 됩니다. 96 | 97 | 우리가 방금 구현한 코드는 큰 문제는 없지만, 이걸 깔끔하게 해결 할 방법을 알고 나면 좀 맘에 들지 않는 코드의 형태입니다. 98 | 99 | 이 코드를 더욱 깔끔하게 작성하는 방법을 알려드리겠습니다. 100 | 101 | ```javascript 102 | function getSound(animal) { 103 | const sounds = { 104 | 개: '멍멍!', 105 | 고양이: '야옹~', 106 | 참새: '짹짹', 107 | 비둘기: '구구 구 구' 108 | }; 109 | return sounds[animal] || '...?'; 110 | } 111 | 112 | console.log(getSound('개')); // 멍멍! 113 | console.log(getSound('비둘기')); // 구구 구 구 114 | ``` 115 | 116 | 훨씬 더 간략하고 가독성도 좋지요? 이렇게 특정 값에 따라 반환해야 하는 값이 다른 조건이 여러가지 있을 때는 객체를 활용하면 좋습니다. 117 | 118 | 반면, 값에 따라 실행해야 하는 코드 구문이 다를 때는 어떻게 해야 할까요? 119 | 120 | 그럴 떄는 객체에 함수를 넣으면 됩니다. 121 | 122 | ```javascript 123 | function makeSound(animal) { 124 | const tasks = { 125 | 개() { 126 | console.log('멍멍'); 127 | }, 128 | 고양이() { 129 | console.log('고양이'); 130 | }, 131 | 비둘기() { 132 | console.log('구구 구 구'); 133 | } 134 | }; 135 | if (!tasks[animal]) { 136 | console.log('...?'); 137 | return; 138 | } 139 | tasks[animal](); 140 | } 141 | 142 | getSound('개'); 143 | getSound('비둘기'); 144 | ``` 145 | 146 | 이것을 잘 알아두면, 앞으로 매우 쓸모 있을 것입니다. 147 | 148 | -------------------------------------------------------------------------------- /useful/06-destructuring.md: -------------------------------------------------------------------------------- 1 | ## 06. 비구조화 할당 (구조분해) 문법 2 | 3 | 이번에는 1장 섹션 6 에서도 배웠던 [비구조화 할당](https://learnjs.vlpt.us/basics/06-object.html#%EA%B0%9D%EC%B2%B4-%EB%B9%84%EA%B5%AC%EC%A1%B0%ED%99%94-%ED%95%A0%EB%8B%B9) 문법을 잘 활용하는 방법에 대해서 알아보겠습니다. 4 | 5 | 이전에 배웠던것을 복습해보자면, 비구조화 할당 문법을 사용하면 다음과 같이 객체 안에 있는 값을 추출해서 변수 혹은 상수로 바로 선언해 줄 수있었죠? 6 | 7 | ```javascript 8 | const object = { a: 1, b: 2 }; 9 | 10 | const { a, b } = object; 11 | 12 | console.log(a); // 1 13 | console.log(b); // 2 14 | ``` 15 | 16 | 그리고, 함수의 파라미터에서도 비구조화 할당을 할 수 있는것도 배웠습니다. 17 | 18 | ```javascript 19 | const object = { a: 1, b: 2 }; 20 | 21 | function print({ a, b }) { 22 | console.log(a); 23 | console.log(b); 24 | } 25 | 26 | print(object); 27 | ``` 28 | 29 | 그런데 여기서 만약 b 값이 주어지지 않았다고 가정해봅시다. 30 | 31 | ```javascript 32 | const object = { a: 1 }; 33 | 34 | function print({ a, b }) { 35 | console.log(a); 36 | console.log(b); 37 | } 38 | 39 | print(object); 40 | // 1 41 | // undefined 42 | ``` 43 | 44 | 두번째 출력에서 undefined가 나타날 것입니다. 45 | 46 | ### 비구조화 할당시 기본값 설정 47 | 48 | 이러한 상황에 b 값에 기본 값을 주고 싶다면 이렇게 해줄 수 있습니다. 49 | 50 | ```javascript 51 | const object = { a: 1 }; 52 | 53 | function print({ a, b = 2 }) { 54 | console.log(a); 55 | console.log(b); 56 | } 57 | 58 | print(object); 59 | // 1 60 | // 2 61 | ``` 62 | 63 | 64 | 이는 꼭 함수의 파라미터에서만 할 수 있는 것은 아닙니다. 65 | 66 | ```javascript 67 | const object = { a: 1 }; 68 | 69 | const { a, b = 2 } = object; 70 | 71 | console.log(a); // 1 72 | console.log(b); // 2 73 | ``` 74 | 75 | 76 | ### 비구조화 할당시 이름 바꾸기 77 | 78 | 이번에는, 비구조화 할당을 하는 과정에서 선언 할 값의 이름을 바꾸는 방법을 알아보겠습니다. 79 | 80 | 예를 들어서 다음과 같은 코드가 있다고 가정해봅시다. 81 | 82 | ```javascript 83 | const animal = { 84 | name: '멍멍이', 85 | type: '개' 86 | }; 87 | 88 | const nickname = animal.name; 89 | 90 | console.log(nickname); // 멍멍이 91 | ``` 92 | 93 | 위 코드에서는 animal.name 값을 nickname 값에 담고 있는데요, 이름이 같다면 그냥 우리가 이전에 배웠던 대로 비구조화 할당을 쓰면 되는데 지금은 이름이 서로 다릅니다. 94 | 95 | 이러한 상황에서는 : 문자를 사용해서 이름을 바꿔줄 수 있습니다. 96 | 97 | ```javascript 98 | const animal = { 99 | name: '멍멍이', 100 | type: '개' 101 | }; 102 | 103 | const { name: nickname } = animal 104 | console.log(nickname); 105 | ``` 106 | 107 | 위 코드는 'animal 객체 안에 있는 name 을 nickname 이라고 선언하겠다.' 라는 의미입니다. 108 | 109 | ### 배열 비구조화 할당 110 | 111 | 비구조화 할당은 객체에만 할 수 있는 것이 아닙니다. 배열에서 할 수 있어요. 112 | 113 | 예시 코드를 봅시다. 114 | 115 | ```javascript 116 | const array = [1, 2]; 117 | const [one, two] = array; 118 | 119 | console.log(one); 120 | console.log(two); 121 | ``` 122 | 123 | 이 문법은 배열 안에 있는 원소를 다른 이름으로 새로 선언해주고 싶을 때 사용하면 매우 유용합니다. 124 | 125 | 객체 비구조화 할당과 마찬가지로, 기본값 지정이 가능합니다. 126 | 127 | ```javascript 128 | const array = [1]; 129 | const [one, two = 2] = array; 130 | 131 | console.log(one); 132 | console.log(two); 133 | ``` 134 | 135 | ### 깊은 값 비구조화 할당 136 | 137 | 객체의 깊숙한 곳에 들어있는 값을 꺼내는 방법을 알아봅시다. 138 | 139 | 예를들어서 다음과 같은 객체가 있다고 가정해봅시다. 140 | 141 | ```javascript 142 | const deepObject = { 143 | state: { 144 | information: { 145 | name: 'velopert', 146 | languages: ['korean', 'english', 'chinese'] 147 | } 148 | }, 149 | value: 5 150 | }; 151 | ``` 152 | 153 | 여기서, name, languages, value 값들을 밖으로 꺼내주고 싶다면 어떻게 해야 할까요? 이럴땐 두가지 해결 방법이 있는데요, 첫번째는 비구조화 할당 문법을 두번 사용하는 것입니다. 154 | 155 | ```javascript 156 | const deepObject = { 157 | state: { 158 | information: { 159 | name: 'velopert', 160 | languages: ['korean', 'english', 'chinese'] 161 | } 162 | }, 163 | value: 5 164 | }; 165 | 166 | const { name, languages } = deepObject.state.information; 167 | const { value } = deepObject; 168 | 169 | const extracted = { 170 | name, 171 | languages, 172 | value 173 | }; 174 | 175 | console.log(extracted); // {name: "velopert", languages: Array[3], value: 5} 176 | ``` 177 | 178 | 그런데 잠깐! 지금 extracted 객체를 선언 할 때 이런식으로 했는데요 179 | 180 | ```javascript 181 | const extracted = { 182 | name, 183 | languages, 184 | value 185 | } 186 | ``` 187 | 188 | 이 코드는 다음 코드와 똑같습니다. 189 | ```javascript 190 | const extracted = { 191 | name: name, 192 | languages: languages, 193 | value: value 194 | } 195 | ``` 196 | 197 | 만약에 key 이름으로 선언된 값이 존재하다면, 바로 매칭시켜주는 문법입니다. 이 문법은 ES6 의 object-shorthand 문법이라고 부릅니다. (이름은 굳이 알아둘 필요는 없습니다..!) 198 | 199 | 다시 본론으로 돌아와서, 아까 deepObject 객체에서 names, languages, value 를 추출하는 과정에서 비구조화 할당을 두번 했었죠? 200 | 201 | 이번엔 두번째 방법, 한번에 모두 추출하는 방법을 알아보겠습니다. 202 | 203 | ```javascript 204 | const deepObject = { 205 | state: { 206 | information: { 207 | name: 'velopert', 208 | languages: ['korean', 'english', 'chinese'] 209 | } 210 | }, 211 | value: 5 212 | }; 213 | 214 | const { 215 | state: { 216 | information: { name, languages } 217 | }, 218 | value 219 | } = deepObject; 220 | 221 | const extracted = { 222 | name, 223 | languages, 224 | value 225 | }; 226 | 227 | console.log(extracted); 228 | ``` 229 | 230 | 이렇게 하면 깊숙히 안에 들어있는 값도 객체에서 바로 추출 할 수 있답니다. 231 | 232 |  233 | 234 | 위 이미지에서 주황색으로 나타난 값들이 추출 된 것입니다. 반면, 빨간색으로 나타난 값들은 따로 추출되지 않으니 참고하세요. 235 | 236 | 이렇게 깊숙한 객체안에 있는 값을 추출하는 방법을 알아보았는데요, 사람들마다 성향이 다르겠지만, 저는 개인적으로 한번에 다 추출하는 것 보다는 여러번에 걸쳐서 추출하는 것이 더욱 코드가 깔끔하다고 생각합니다. 정해진 답은 없으니 여러분이 편한 방식을 택해서 하세요. 237 | 238 | -------------------------------------------------------------------------------- /useful/07-spread-and-rest.md: -------------------------------------------------------------------------------- 1 | ## 07. spread 와 rest 2 | 3 | 이번에는 ES6 에서 도입된 spread 와 rest 문법에 대해서 알아보겠습니다. 서로 완전히 다른 문법인데요, 은근히 좀 비슷합니다. 4 | 5 | ### spread 6 | 7 | 일단 spread 문법부터 알아봅시다. spread 라는 단어가 가지고 있는 의미는 펼치다, 퍼뜨리다 입니다. 이 문법을 사용하면, 객체 혹은 배열을 펼칠수있습니다. 8 | 9 | 예를 들어서 다음과 같은 객체들이 있다고 가정해봅시다. 10 | 11 | ```javascript 12 | const slime = { 13 | name: '슬라임' 14 | }; 15 | 16 | const cuteSlime = { 17 | name: '슬라임', 18 | attribute: 'cute' 19 | }; 20 | 21 | const purpleCuteSlime = { 22 | name: '슬라임', 23 | attribute: 'cute', 24 | color: 'purple' 25 | }; 26 | 27 | console.log(slime); 28 | console.log(cuteSlime); 29 | console.log(purpleCuteSlime); 30 | ``` 31 | 32 |  33 | 34 | 이 코드에서는 먼저 slime 이라는 객체를 선언했습니다. 그리고 cuteSlime 이라는 객체를 만들었는데요, 기존에 선언한 slime 을 건들이지 않고 새로운 객체를 만들어서 slime 이 가지고 있는 값을 그대로 사용하였습니다. 35 | 36 | 그 다음에는 purpleCuteSlime 이라는 객체를 만들었는데요, 이 객체는 cuteSlime 이 가지고 있는 속성을 그대로 사용하면서 추가적으로 color 가 추가되었습니다. 37 | 38 | 위 코드에서의 핵심은, 기존의 것을 건들이지 않고, 새로운 객체를 만든다는 것 인데요, 이러한 상황에 사용 할 수 있는 유용한 문법이 spread 입니다. 39 | 40 | 아까 코드는 spread 문법을 사용하면 다음과 같이 작성 할 수 있습니다. 41 | 42 | ```javascript 43 | const slime = { 44 | name: '슬라임' 45 | }; 46 | 47 | const cuteSlime = { 48 | ...slime, 49 | attribute: 'cute' 50 | }; 51 | 52 | const purpleCuteSlime = { 53 | ...cuteSlime, 54 | color: 'purple' 55 | }; 56 | 57 | console.log(slime); 58 | console.log(cuteSlime); 59 | console.log(purpleCuteSlime); 60 | ``` 61 | 62 | 여기서 사용한 ... 문자가 바로 spread 연산자입니다. 63 | 64 | spread 연산자는 배열에서도 사용 할 수 있습니다. 65 | 66 | 67 | ```javascript 68 | const animals = ['개', '고양이', '참새']; 69 | const anotherAnimals = [...animals, '비둘기']; 70 | console.log(animals); 71 | console.log(anotherAnimals); 72 | ``` 73 | 74 |  75 | 76 | 기존의 animals 는 건드리지 않으면서, 새로운 anotherAnimals 배열에 animals 가 가지고 있는 내용을 모두 집어넣고, '비둘기' 라는 항목을 추가적으로 넣었습니다. 77 | 78 | 배열에서 spread 연산자를 여러번 사용 할 수도 있습니다. 79 | 80 | ```javascript 81 | const numbers = [1, 2, 3, 4, 5]; 82 | 83 | const spreadNumbers = [...numbers, 1000, ...numbers]; 84 | console.log(spreadNumbers); // [1, 2, 3, 4, 5, 1000, 1, 2, 3, 4, 5] 85 | ``` 86 | 87 | 88 | ### rest 89 | 90 | rest는 생김새는 spread 랑 비슷한데, 역할이 매우 다릅니다. 91 | 92 | rest는 객체, 배열, 그리고 함수의 파라미터에서 사용이 가능합니다. 93 | 94 | #### 객체에서의 rest 95 | 96 | 우선 객체에서의 예시를 알아볼까요? 97 | 98 | ```javascript 99 | const purpleCuteSlime = { 100 | name: '슬라임', 101 | attribute: 'cute', 102 | color: 'purple' 103 | }; 104 | 105 | const { color, ...rest } = purpleCuteSlime; 106 | console.log(color); 107 | console.log(rest); 108 | ``` 109 | 110 |  111 | 112 | rest 안에 name 값을 제외한 값이 들어있습니다. 113 | 114 | rest 는 객체와 배열에서 사용 할 때는 이렇게 비구조화 할당 문법과 함께 사용됩니다. 주로 사용 할때는 위와 같이 rest 라는 키워드를 사용하게 되는데요, 추출한 값의 이름이 꼭 rest 일 필요는 없습니다. 115 | 116 | ```javascript 117 | const purpleCuteSlime = { 118 | name: '슬라임', 119 | attribute: 'cute', 120 | color: 'purple' 121 | }; 122 | 123 | const { color, ...cuteSlime } = purpleCuteSlime; 124 | console.log(color); 125 | console.log(cuteSlime); 126 | ``` 127 | 128 | 이렇게 해도 무방합니다. 129 | 130 | 이어서, attribute 까지 없앤 새로운 객체를 만들고 싶다면 이렇게 해주면 되겠죠. 131 | 132 | ```javascript 133 | const purpleCuteSlime = { 134 | name: '슬라임', 135 | attribute: 'cute', 136 | color: 'purple' 137 | }; 138 | 139 | const { color, ...cuteSlime } = purpleCuteSlime; 140 | console.log(color); 141 | console.log(cuteSlime); 142 | 143 | const { attribute, ...slime } = cuteSlime; 144 | console.log(attribute); 145 | console.log(slime); 146 | ``` 147 | 148 |  149 | 150 | #### 배열에서의 rest 151 | 152 | 다음, 배열에서의 사용 예시를 알아봅시다. 153 | 154 | ```javascript 155 | const numbers = [0, 1, 2, 3, 4, 5, 6]; 156 | 157 | const [one, ...rest] = numbers; 158 | 159 | console.log(one); 160 | console.log(rest); 161 | ``` 162 | 163 |  164 | 165 | 배열 비구조화 할당을 통하여 원하는 값을 밖으로 꺼내고, 나머지 값을 rest 안에 넣었습니다. 166 | 167 | 반면 이렇게 할 수는 없답니다. 168 | 169 | ```javascript 170 | const numbers = [0, 1, 2, 3, 4, 5, 6]; 171 | 172 | const [..rest, last] = numbers; 173 | ``` 174 | 175 |  176 | 177 | 178 | #### 함수 파라미터에서의 rest 179 | 180 | rest 를 함수파라미터에서 사용 할 수도 있습니다. 예를 들어서 우리가 파라미터로 넣어준 모든 값들을 합해주는 함수를 만들어주고 싶다고 가정해봅시다. 181 | 182 | ```javascript 183 | function sum(a, b, c, d, e, f, g) { 184 | let sum = 0; 185 | if (a) sum += a; 186 | if (b) sum += b; 187 | if (c) sum += c; 188 | if (d) sum += d; 189 | if (e) sum += e; 190 | if (f) sum += f; 191 | if (g) sum += g; 192 | return sum; 193 | } 194 | 195 | const result = sum(1, 2, 3, 4, 5, 6); 196 | console.log(result); 197 | ``` 198 | 199 | 위에서의 sum 함수는 7개의 파라미터를 받아오는데, 아래에서 사용 할때에는 6개만 넣어줬습니다. 그러면, g 값이 undefined 가 되기 때문에 sum 에 더하는 과정에서 += undefined 를 하게 되면 결과는 NaN 이 되버립니다. 그렇기 때문에 함수에서 하나하나 유효한 값인지 확인을 해줬지요. 200 | 201 | 함수의 파라미터가 몇개가 될 지 모르는 상황에서 rest 파라미터를 사용하면 매우 유용합니다. 코드를 다음과 같이 수정해보세요. 202 | 203 | ```javascript 204 | function sum(...rest) { 205 | return rest; 206 | } 207 | 208 | const result = sum(1, 2, 3, 4, 5, 6); 209 | console.log(result); 210 | ``` 211 | 212 |  213 | 214 | result 가 가르키고 있는 것은 함수에서 받아온 파라미터들로 이루어진 배열입니다. 우리가 이제 파라미터들이 들어가있는 배열을 받았으니, 그냥 모두 더해주면 되겠죠? 215 | 216 | ```javascript 217 | function sum(...rest) { 218 | return rest.reduce((acc, current) => acc + current, 0); 219 | } 220 | 221 | const result = sum(1, 2, 3, 4, 5, 6); 222 | console.log(result); // 21 223 | ``` 224 | 225 | 여기서 reduce 함수가 사용 됐는데, reduce 를 잘 모르겠으면 [1장 섹션 9](https://learnjs.vlpt.us/basics/09-array-functions.html#reduce)를 복습하고 오세요. 226 | 227 | ### 함수 인자와 spread 228 | 229 | 이번에는, 다시 아까 배웠던 spread 로 돌아와서 한가지를 더 가르쳐드리겠습니다. 바로 함수의 인자와 spread 인데요, 만약 프로그래밍을 처음 배우신다면 파라미터와 인자가 좀 헷갈릴 수 있습니다. 이에 대해서 간단하게 설명 드려볼게요. 230 | 231 | ```javascript 232 | const myFunction(a) { // 여기서 a 는 파라미터 233 | console.log(a); // 여기서 a 는 인자 234 | } 235 | 236 | myFunction('hello world'); // 여기서 'hello world' 는 인자 237 | ``` 238 | 239 | 함수에서 값을 읽을때, 그 값들은 파라미터라고 부릅니다. 240 | 그리고 함수에서 값을 넣어줄 때, 그 값들은 인자라고 부릅니다. 241 | 242 | 인자가 무엇인지 이해를 하셨다면 이제 함수인자와 spread 문법을 사용하는 것에 대하여 알아볼게요. 243 | 244 | 우리가 방금 함수파라미터와 rest 를 사용한 것과 비슷한데, 반대의 역할입니다. 예를 들어서, 우리가 배열 안에 있는 원소들을 모두 파라미터로 넣어주고 싶다고 가정해보겠습니다. 245 | 246 | 247 | ```javascript 248 | function sum(...rest) { 249 | return rest.reduce((acc, current) => acc + current, 0); 250 | } 251 | 252 | const numbers = [1, 2, 3, 4, 5, 6]; 253 | const result = sum( 254 | numbers[0], 255 | numbers[1], 256 | numbers[2], 257 | numbers[3], 258 | numbers[4], 259 | numbers[5] 260 | ); 261 | console.log(result); 262 | ``` 263 | 264 | 굉장히 불편하죠? 만약에 sum함수를 사용 할 때 인자 부분에서 spread 를 사용하면 다음과 같이 표현이 가능합니다. 265 | 266 | ```javascript 267 | function sum(...rest) { 268 | return rest.reduce((acc, current) => acc + current, 0); 269 | } 270 | 271 | const numbers = [1, 2, 3, 4, 5, 6]; 272 | const result = sum(...numbers); 273 | console.log(result); 274 | ``` 275 | 276 | 어떤가요? 정말 편하죠? 277 | 278 | 이렇게, spread 와 rest 를 잘 사용하면 앞으로 보기 깔끔한 코드를 작성하는 것에 큰 도움을 줄 것입니다. 279 | 280 | 281 | ### 퀴즈 282 | 283 | 함수에 n 개의 숫자들이 파라미터로 주어졌을 때, 그 중 가장 큰 값을 알아내세요. 284 | 285 | ```javascript 286 | function max() { 287 | return 0; 288 | } 289 | 290 | const result = max(1, 2, 3, 4, 10, 5, 6, 7); 291 | console.log(result); 292 | ``` 293 | 294 | [](https://codesandbox.io/s/gifted-davinci-qxqzn?fontsize=14) 295 | 296 | 위 CodeSandbox 링크에서 우측에 뜨는 Tests 를 통과시키시면 됩니다. 297 | 298 | [정답](https://codesandbox.io/s/silly-napier-pippm) 299 | 300 | -------------------------------------------------------------------------------- /useful/08-scope.md: -------------------------------------------------------------------------------- 1 | ## 08. 자바스크립트의 Scope 에 대한 이해 2 | 3 | 이번에는 자바스크립트의 Scope 에 대해서 알아봅시다. Scope 란, 우리가 변수 혹은 함수를 선언하게 될 때 해당 변수 또는 함수가 유효한 범위를 의미합니다. Scope 는 총 3가지 종류가있습니다. 4 | 5 | 1. **Global (전역) Scope**: 코드의 모든 범위에서 사용이 가능합니다. 6 | 2. **Function (함수) Scope**: 함수 안에서만 사용이 가능합니다. 7 | 3. **Block (블록) Scope**: if, for, switch 등 특정 블록 내부에서만 사용이 가능합니다. 8 | 9 | 10 | ### 예시를 통한 Scope 이해 11 | 12 | 한번, 예시 코드를 보고 Scope 를 이해해봅시다. 13 | 14 | ```javascript 15 | const value = 'hello!'; 16 | 17 | function myFunction() { 18 | console.log('myFunction: '); 19 | console.log(value); 20 | } 21 | 22 | function otherFunction() { 23 | console.log('otherFunction: '); 24 | const value = 'bye!'; 25 | console.log(value); 26 | } 27 | 28 | myFunction(); 29 | otherFunction(); 30 | 31 | console.log('global scope: '); 32 | console.log(value); 33 | 34 | ``` 35 | 36 | 위 코드의 결과는 다음과 같습니다. 37 | 38 |  39 | 40 | 코드의 맨 윗줄에서 선언된 `value` 값은 Global Scope 로 선언된 값입니다. Global Scope 로 선언된 값은 어디서든지 사용이 가능합니다. `myFunction` 에서 바로 사용을 할 수 있었지요? 41 | 42 | `otherFunction` 에서는 함수 내부에서 `value` 값을 `'bye!'` 로 새로 선언을 해주었습니다. 이렇게 되면, value 라는 값은 Function Scope 로 지정이 되서 해당 값은 `otherFunction` 내부에서만 유효한 값이 됩니다. 이렇게 값을 설정한다고 해서 기존에 Global Scope 로 선언된 `value` 값이 바뀌지 않습니다. 43 | 44 | 또 다른 예시를 확인해봅시다. 45 | 46 | ```javascript 47 | const value = 'hello!'; 48 | 49 | function myFunction() { 50 | const value = 'bye!'; 51 | const anotherValue = 'world'; 52 | function functionInside() { 53 | console.log('functionInside: '); 54 | console.log(value); 55 | console.log(anotherValue); 56 | } 57 | functionInside(); 58 | } 59 | 60 | 61 | myFunction() 62 | console.log('global scope: '); 63 | console.log(value); 64 | console.log(anotherValue); 65 | ``` 66 | 67 |  68 | 69 | `myFunction` 내부에 `anotherValue` 라는 새로운 값을 선언했고, `functionInside` 라는 함수도 선언을 했습니다. `functionInside` 함수에서는 `myFunction` 에서 선언한 `value` 값과 `anotherValue` 값을 조회 할 수 있습니다. 70 | 71 | 반면, `myFunction` 밖에서는 `anotherValue` 를 조회 할 수 없습니다. 72 | 73 | 이제, 또 다른 예시를 알아봅시다. 74 | 75 | ```javascript 76 | const value = 'hello!'; 77 | 78 | function myFunction() { 79 | const value = 'bye!'; 80 | if (true) { 81 | const value = 'world'; 82 | console.log('block scope: '); 83 | console.log(value); 84 | } 85 | console.log('function scope: '); 86 | console.log(value); 87 | } 88 | 89 | myFunction(); 90 | console.log('global scope: '); 91 | console.log(value); 92 | ``` 93 | 94 |  95 | 96 | `const` 로 선언한 값은 Block Scope 로 선언이 됩니다. 따라서, if 문 같은 블록 내에서 새로운 변수/상수를 선언하게 된다면, 해당 블록 내부에서만 사용이 가능하며, 블록 밖의 범위에서 똑같은 이름을 가진 값이 있다고 해도 영향을 주지 않습니다. 97 | 98 | `let` 또한 마찬가지 입니다. 99 | 100 | 하지만 `var` 는 어떨까요? 101 | 102 | ```javascript 103 | var value = 'hello!'; 104 | 105 | function myFunction() { 106 | var value = 'bye!'; 107 | if (true) { 108 | var value = 'world'; 109 | console.log('block scope: '); 110 | console.log(value); 111 | } 112 | console.log('function scope: '); 113 | console.log(value); 114 | } 115 | 116 | myFunction(); 117 | console.log('global scope: '); 118 | console.log(value); 119 | ``` 120 | 121 | `var` 는 Function Scope 로 선언이 되므로, if 문 블록 내부에서 선언한 value 값이 블록 밖의 value 에도 영향을 미치게 됩니다. 122 | 123 |  124 | 125 | 126 | ### Hoisting 이해하기 127 | 128 | Hoisting 이란, 자바스크립트에서 아직 선언되지 않은 함수/변수를 "끌어올려서" 사용 할 수 있는 자바스크립트의 작동 방식을 의미합니다. 129 | 130 | 다음 코드를 확인해보세요. 131 | 132 | 133 | ```javascript 134 | myFunction(); 135 | 136 | function myFunction() { 137 | console.log('hello world!'); 138 | } 139 | ``` 140 | 141 | 위 코드에서는 `myFunction` 함수를 선언하기 전에, `myFunction()` 을 호출해주었습니다. 함수가 아직 선언되지 않았음에도 불구하고 코드는 정상적으로 작동하게 됩니다. 142 | 143 | 이게 잘 작동하는 이유는, 자바스크립트 엔진이 위 코드를 해석하는 과정에서, 다음과 같이 받아들이게 되기 때문입니다. 144 | 145 | ```javascript 146 | function myFunction() { 147 | console.log('hello world!'); 148 | } 149 | 150 | myFunction(); 151 | ``` 152 | 153 | 이러한 현상을, Hoisting 이라고 부릅니다. 154 | 155 | 변수 또한 Hoisting 됩니다. 156 | 157 | 예를 들어서, 다음과 같은 코드를 실행한다면, 158 | 159 | ```javascript 160 | console.log(number); 161 | ``` 162 | 163 |  164 | 165 | 이런 오류가 발생합니다. 166 | 167 | 그렇지만, 다음과 같은 코드는 168 | 169 | ```javascript 170 | console.log(number); 171 | var number = 2; 172 | ``` 173 | 174 |  175 | 176 | `undefined` 가 출력됩니다. 177 | 178 | 자바스크립트 엔진이 위 코드를 해석 할 때는 다음과 같이 받아들이게 됩니다. 179 | 180 | ```javascript 181 | var number; 182 | console.log(number); 183 | number = 2; 184 | ``` 185 | 186 | 반면, `const` 와 `let` 은 hoisting 이 발생하지 않고, 에러가 발생하게 됩니다. Codesandbox 에서는 자바스크립트가 Babel 이라는 도구에 의하여 `const` 와 `let` 이 `var` 로 변환되기 때문에 오류가 발생하지 않습니다. Chrome 개발자 도구의 콘솔에서 다음 코드를 실행해보세요. (혹은 Codesandbox 의 설정에서 .babelrc 를 비워도 됩니다. 187 | 188 | ```javascript 189 | function fn() { 190 | console.log(a); 191 | let a = 2; 192 | } 193 | fn(); 194 | ``` 195 | 196 |  197 | 198 | Hoisting 은 자바스크립트 엔진이 갖고 있는 성질이며, Hoisting 을 일부러 할 필요는 없지만, 방지하는 것이 좋습니다. 왜냐하면 Hoisting 이 발생하는 코드는 이해하기 어렵기 때문에 유지보수도 힘들어지고 의도치 않는 결과물이 나타나기 쉽기 때문입니다. 199 | 200 | Hoisting 을 방지하기 위해서, 함수의 경우 꼭 선언 후에 호출을 하도록 주의를 하시고, `var` 대신 `const`, `let` 을 위주로 사용하세요. 추가적으로, 나중에 자바스크립트 개발을 본격적으로 하게 될 때에는 ESLint 라는것을 사용하여 Hoisting 이 발생하는 코드는 에디터상에서 쉽게 발견해낼 수 있습니다. -------------------------------------------------------------------------------- /useful/README.md: -------------------------------------------------------------------------------- 1 | # 알고있으면 유용한 자바스크립트 문법 2 | 3 | 이번에는 알고있으면 유용한 다양한 자바스크립트 문법을 알아보게됩니다! 4 | 이번에 소개 할 대부분의 문법은 ES6 이상 버전에서 사용 할 수 있는 문법들입니다. 5 | 그리고, ES6 가 아닌 문법들도 은근히 있습니다. 6 | 7 | 시작해볼까요? 8 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | gitbook-plugin-expandable-chapters@^0.2.0: 6 | version "0.2.0" 7 | resolved "https://registry.yarnpkg.com/gitbook-plugin-expandable-chapters/-/gitbook-plugin-expandable-chapters-0.2.0.tgz#45d7087ae6907a41f48128c54fe56224a9c1ada2" 8 | integrity sha1-RdcIeuaQekH0gSjFT+ViJKnBraI= 9 | --------------------------------------------------------------------------------