├── README.md └── snippets ├── ascending.js ├── bifurcateBy.js ├── clamp.js ├── collectBy.js ├── curry.js ├── descending.js ├── differenceBy.js ├── distance.js ├── dropWhile.js ├── findKey.js ├── flatten.js ├── getValue.js ├── groupBy.js ├── head.js ├── indexBy.js ├── intersectionBy.js ├── isValidDate.js ├── isValidJSON.js ├── memoize.js ├── pipe.js ├── recoverWith.js ├── sleep.js ├── sumBy.js └── tail.js /README.md: -------------------------------------------------------------------------------- 1 | # useful-js-snippets 2 | 3 | > 유용한 자바스크립트 코드 조각들을 모아 놓았습니다. 4 | 5 | ## TOC 6 | 7 | 1. [Reference](#reference) 8 | 2. [Snippets usage](#snippets-usage) 9 | 10 | - [Get Value](#get-value) 11 | - [Clamp](#clamp) 12 | - [Sleep](#sleep) 13 | - [Group By](#group-by) 14 | - [Collect By](#collect-by) 15 | - [Head](#head) 16 | - [Tail](#tail) 17 | - [Flatten](#flatten) 18 | - [Intersection By](#intersection-by) 19 | - [Index By](#index-by) 20 | - [Difference By](#difference-by) 21 | - [Recover With](#recover-with) 22 | - [Distance](#distance) 23 | - [Drop While](#drop-while) 24 | - [Sum By](#sum-by) 25 | - [Ascending](#ascending) 26 | - [Descending](#descending) 27 | - [Find Key](#find-key) 28 | - [Bifurcate](#bifurcate-by) 29 | - [Pipe](#pipe) 30 | - [isVaildJSON](#isvalidjson) 31 | - [isVaildDate](#isvaliddate) 32 | - [Memoization](#memoization) 33 | - [Curry](#curry) 34 | 35 | ## Reference 36 | 37 | - Henrik Larsen Toft's 38 | [20 JavaScript snippets that will make you a better developer](https://levelup.gitconnected.com/20-javascript-snippets-that-will-make-you-a-better-developer-68dfe4bf5019) 39 | - Angelos Chalaris' [30 seconds of code](https://www.30secondsofcode.org/) 40 | - [modern javascript tutorial](https://ko.javascript.info/) 41 | 42 | ## Snippets usage 43 | 44 | #### Get Value 45 | 46 | 함수는 지정된 경로의 값을 반환하고, 값이 없으면 null을 반환합니다. 47 | 48 | ```js 49 | getValue({ a: { b: { c: "d" } } }, "a.b.c"); // = d 50 | ``` 51 | 52 | | Function | Parameter | Description | 53 | | :--------- | :---------------------------- | :------------------------------------------------------ | 54 | | `getValue` | obj: `object`, path: `string` | 유효한 경로라면 값을 리턴하고 아니면 null을 리턴합니다. | 55 | 56 | --- 57 | 58 | #### clamp 59 | 60 | 값이 지정된 범위 내에 있는지 확인하고, 지정된 범위에 값이 없다면 최소값과 최대값에 가장 가까운 값을 반환(클램프)합니다. 61 | 62 | ```js 63 | clamp(0, 10, -5); // = 0 64 | ``` 65 | 66 | | Function | Parameter | Description | 67 | | :------- | :------------------------------------------- | :------------------------------------------------------ | 68 | | `clamp` | min: `number`, max: `number`, value:`number` | 주어진 값을 리턴하거나 최소값 혹은 최대값을 리턴합니다. | 69 | 70 | --- 71 | 72 | #### Sleep 73 | 74 | 다음 작업을 수행하기 전에 지정된 기간(밀리초)을 기다립니다. 75 | 76 | ```js 77 | await sleep(1000); // waits 1 sec 78 | ``` 79 | 80 | | Function | Parameter | Description | 81 | | :------- | :----------------- | :----------------------------- | 82 | | `sleep` | duration: `number` | 주어진 기간동안 딜레이 됩니다. | 83 | 84 | --- 85 | 86 | #### Group By 87 | 88 | keying-function에 따라 개체의 관련 항목을 그룹화하고 색인화합니다. 89 | 90 | ```js 91 | groupBy( 92 | (vehicle) => vehicle.make, 93 | [ 94 | { make: "tesla", model: "3" }, 95 | { make: "tesla", model: "y" }, 96 | { make: "ford", model: "mach-e" }, 97 | ] 98 | ); 99 | // { 100 | // tesla: [ { make: 'tesla', ... }, { make: 'tesla', ... } ], 101 | // ford: [ { make: 'ford', ... } ], 102 | ``` 103 | 104 | | Function | Parameter | Description | 105 | | :-------- | :-------------------------- | :-------------------------- | 106 | | `groupBy` | fn:`Function` list: `Array` | 그룹화된 객체를 반환합니다. | 107 | 108 | --- 109 | 110 | #### Collect By 111 | 112 | keying-function에 따라 관련 항목을 포함하는 하위 리스트를 만듭니다. 113 | 114 | ```js 115 | collectBy( 116 | (vehicle) => vehicle.make, 117 | [ 118 | { make: "tesla", model: "3" }, 119 | { make: "tesla", model: "y" }, 120 | { make: "ford", model: "mach-e" }, 121 | ] 122 | ); 123 | 124 | // [ 125 | // [ { make: 'tesla', ... }, { make: 'tesla', ... } ], 126 | // [ { make: 'ford', ... } ], 127 | // ] 128 | ``` 129 | 130 | | Function | Parameter | Description | 131 | | :---------- | :-------------------------- | :------------------------------- | 132 | | `collectBy` | fn:`Function` list: `Array` | **groupBy에 의존성이 있습니다.** | 133 | 134 | --- 135 | 136 | #### Head 137 | 138 | 리스트의 첫 번째 요소를 가져옵니다. 이 함수는 깨끗하고 읽기 쉬운 코드를 작성하는 데 유용합니다. 139 | 140 | ```js 141 | head([1, 2, 3]); // = 1 142 | head([]); // = undefined 143 | ``` 144 | 145 | | Function | Parameter | Description | 146 | | :------- | :------------ | :--------------------------------------------- | 147 | | `head` | list: `Array` | 첫번째 값을 리턴하거나 undefiend를 리턴합니다. | 148 | 149 | --- 150 | 151 | #### Tail 152 | 153 | 리스트의 첫 번째 요소를 제외한 모든 요소를 ​​가져옵니다. 이 함수는 깨끗하고 읽기 쉬운 코드를 작성하는 데 유용합니다. 154 | 155 | ```js 156 | tail([1, 2, 3]); // = [2, 3] 157 | tail([]); // = [] 158 | ``` 159 | 160 | | Function | Parameter | Description | 161 | | :------- | :------------ | :------------------------------------------------ | 162 | | `tail` | list: `Array` | 첫 번째 요소를 제외한 나머지의 배열을 리턴합니다. | 163 | 164 | #### Flatten 165 | 166 | 중첩된 하위 리스트에서 모든 항목을 재귀적으로 가져와서 플랫 리스트를 만듭니다. 167 | 168 | ```js 169 | flatten([[1, 2, [3, 4], 5, [6, [7, 8]]]]); // = [1, 2, 3, 4, 5, 6, 7, 8] 170 | ``` 171 | 172 | | Function | Parameter | Description | 173 | | :-------- | :------------ | :---------------------------------------------- | 174 | | `flatten` | list: `Array` | 다차원 배열을 입력받아 1차원 배열을 리턴합니다. | 175 | 176 | --- 177 | 178 | #### Intersection By 179 | 180 | keying-function에 의해 정의된 대로 두 목록에 존재하는 모든 값을 찾습니다. (교집합) 181 | 182 | ```js 183 | intersectionBy((v) => v, [1, 2, 3], [2, 3, 4]); // = [2, 3] 184 | intersectionBy( 185 | (v) => v.a, 186 | [{ a: 1 }, { a: 2 }], 187 | [{ a: 2 }, { a: 3 }, { a: 4 }] 188 | ); // = [{ a: 2 }]; 189 | ``` 190 | 191 | | Function | Parameter | Description | 192 | | :--------------- | :------------------------------------------- | :------------------------ | 193 | | `intersectionBy` | fn: `Function` listA: `Array` listB: `Array` | 교집합 배열을 리턴합니다. | 194 | 195 | --- 196 | 197 | #### Index By 198 | 199 | keying-function에 의해 `결정된 값`으로 리스트의 각 요소를 인덱싱합니다. 200 | 201 | ```js 202 | indexBy((val) => val.a, [{ a: 1 }, { a: 2 }, { a: 3 }]); 203 | // = { 1: { a: 1 }, 2: { a:2 }, 3: { a: 3 } } 204 | ``` 205 | 206 | | Function | Parameter | Description | 207 | | :-------- | :--------------------------- | :-------------------------- | 208 | | `indexBy` | fn: `Function` list: `Array` | 인덱스된 객체를 반환합니다. | 209 | 210 | --- 211 | 212 | #### Difference By 213 | 214 | 첫 번째 매개변수인 리스트에서 두 번째 매개변수인 리스트에 없는 모든 항목을 찾아서 새로운 리스트를 반환합니다. 215 | 216 | > keying-function에 의해 결정됩니다. 217 | 218 | ```js 219 | differenceBy((val) => val, [1, 2, 3], [3, 4, 5]); // = [1,2] 220 | differenceBy( 221 | (vehicle) => vehicle.make, 222 | [{ make: "tesla" }, { make: "ford" }, { make: "gm" }], 223 | [{ make: "tesla" }, { make: "bmw" }, { make: "audi" }] 224 | ); // = [{ make: 'ford' }, { make: 'gm' }] 225 | ``` 226 | 227 | | Function | Parameter | Description | 228 | | :------------- | :------------------------------------------- | :------------------------ | 229 | | `differenceBy` | fn: `Function` listA: `Array` listB: `Array` | **indexBy에 의존합니다.** | 230 | 231 | --- 232 | 233 | #### Recover With 234 | 235 | 주어진 함수에서 오류가 발생하면 기본값을 반환합니다. 236 | 237 | ```js 238 | recoverWith("A", (val) => val, "B"); // = B 239 | recoverWith("A", () => { 240 | throw new Error(); 241 | }); // = 'A' 242 | ``` 243 | 244 | | Function | Parameter | Description | 245 | | :------------ | :--------------------------------- | :--------------------------------------------------------------- | 246 | | `recoverWith` | defaultValue: `any` fn: `Function` | 두 번째 매개변수 이후의 매개변수는 주어진 함수의 매개변수입니다. | 247 | 248 | --- 249 | 250 | #### Distance 251 | 252 | 두 점 p1과 p2 사이의 유클리드 거리를 계산합니다. (두 점사이의 거리 계산) 253 | 254 | ```js 255 | distance([0, 1], [5, 4]); // = 5.8309518948453 256 | ``` 257 | 258 | | Function | Parameter | Description | 259 | | :--------- | :-------------------------------------- | :-------------------- | 260 | | `distance` | p1: `Array` p2: `Array` | 두 점사이의 거리 계산 | 261 | 262 | --- 263 | 264 | #### Drop While 265 | 266 | 첫 번째 요소에서부터 시작하여 조건 함수가 충족될 때까지 목록에서 요소를 삭제합니다. 267 | 268 | ```js 269 | dropWhile((val) => val < 5, [1, 2, 3, 4, 5, 6, 7]); // = [5,6,7] 270 | ``` 271 | 272 | | Function | Parameter | Description | 273 | | :---------- | :----------------------------- | :----------------- | 274 | | `dropWhile` | pred: `Function` list: `Array` | 배열을 리턴합니다. | 275 | 276 | --- 277 | 278 | #### Sum By 279 | 280 | 각 요소의 개별 값을 발행하는 함수가 주어지면 리스트에 있는 모든 요소의 합을 계산합니다. 281 | 282 | ```js 283 | sumBy( 284 | (product) => product.price, 285 | [ 286 | { name: "pizza", price: 10 }, 287 | { name: "pepsi", price: 5 }, 288 | { name: "salad", price: 5 }, 289 | ] 290 | ); // = 20 291 | ``` 292 | 293 | | Function | Parameter | Description | 294 | | :------- | :--------------------------- | :--------------------------- | 295 | | `sumBy` | fn: `Function` list: `Array` | 총합(`number`)을 리턴합니다. | 296 | 297 | --- 298 | 299 | #### Ascending 300 | 301 | 평가 함수가 주어지면 오름차순으로 비교하는 함수를 만듭니다. 302 | 303 | ```js 304 | const byPrice = ascending((val) => val.price); 305 | [{ price: 300 }, { price: 100 }, { price: 200 }].sort(byPrice); 306 | // = [{ price: 100 }, { price: 200 }, { price: 300 }] 307 | ``` 308 | 309 | | Function | Parameter | Description | 310 | | :---------- | :------------- | :----------------------------------- | 311 | | `ascending` | fn: `Function` | 평가함수는 비교할 속성을 반환합니다. | 312 | 313 | --- 314 | 315 | #### Descending 316 | 317 | 평가 함수가 주어지면 내림차순으로 비교하는 함수를 만듭니다. 318 | 319 | ```js 320 | const byPrice = descending((val) => val.price); 321 | [{ price: 300 }, { price: 100 }, { price: 200 }].sort(byPrice); 322 | // = [{ price: 300 }, { price: 200 }, { price: 100 }] 323 | ``` 324 | 325 | | Function | Parameter | Description | 326 | | :----------- | :------------- | :----------------------------------- | 327 | | `descending` | fn: `Function` | 평가함수는 비교할 속성을 반환합니다. | 328 | 329 | --- 330 | 331 | #### Find Key 332 | 333 | 인덱스 내에서 주어진 조건을 만족하는 첫 번째 키를 반환합니다. 334 | 335 | ```js 336 | findKey((car) => !car.available, { 337 | tesla: { available: true }, 338 | ford: { available: false }, 339 | gm: { available: true }, 340 | }); // = "ford" 341 | ``` 342 | 343 | | Function | Parameter | Description | 344 | | :-------- | :------------------------------------- | :------------------------------------- | 345 | | `findKey` | predicate: `Function`, index: `Object` | 만족하는 첫 번째 키 이름을 반환합니다. | 346 | 347 | --- 348 | 349 | #### Bifurcate By 350 | 351 | 주어진 리스트의 값을 두 개의 리스트으로 나눕니다. 하나는 평가 함수가 참으로 평가되는 값을 포함하고 또 다른 리스트는 거짓인 값들을 포함합니다. 352 | 353 | ```js 354 | bifurcateBy((val) => val > 0, [-1, 2, -3, 4]); 355 | // = [[2, 4], [-1, -3]] 356 | ``` 357 | 358 | | Function | Parameter | Description | 359 | | :------------ | :----------------------------------- | :----------------------- | 360 | | `bifurcateBy` | predicate: `Function`, list: `Array` | 2차원 배열을 리턴합니다. | 361 | 362 | --- 363 | 364 | #### Pipe 365 | 366 | 왼쪽에서 오른쪽으로 함수 합성을 수행합니다. 첫 함수의 결과는 두 번째 함수에 전달되고 두 번째 결과는 세 번째 함수에 전달되는 식으로 모든 기능이 처리될 때까지 계속됩니다. 367 | 368 | ```js 369 | pipe([Math.abs, Math.floor, (val) => -val], 4.2); // = -4 370 | pipe([(a, b) => a - b, Math.abs], 5, 10); // = 5 371 | ``` 372 | 373 | | Function | Parameter | Description | 374 | | :------- | :-------------------------------------- | :---------------------- | 375 | | `pipe` | functions: `Array`, [args...] | 함수 합성을 수행합니다. | 376 | 377 | --- 378 | 379 | #### isValidJSON 380 | 381 | 주어진 JSON 문자열이 유효한지 판단합니다. 382 | 383 | ```js 384 | isValidJSON('{"name":"Adam","age":20}'); // true 385 | isValidJSON('{"name":"Adam",age:"20"}'); // false 386 | isValidJSON(null); // true 387 | ``` 388 | 389 | | Function | Parameter | Description | 390 | | :------------ | :------------ | :--------------------------------- | 391 | | `isValidJSON` | str: `string` | JSON 문자열이 유효한지 검사합니다. | 392 | 393 | --- 394 | 395 | ### isValidDate 396 | 397 | 주어진 매개변수가 유효한 `date` 값인지 판단합니다. 398 | 399 | ```js 400 | isValidDate("December 17, 1995 03:24:00"); // true 401 | isValidDate("1995-12-17T03:24:00"); // true 402 | isValidDate("1995-12-17 T03:24:00"); // false 403 | isValidDate("Duck"); // false 404 | isValidDate(1995, 11, 17); // true 405 | isValidDate(1995, 11, 17, "Duck"); // false 406 | isValidDate({}); // false 407 | ``` 408 | 409 | | Function | Parameter | Description | 410 | | :------------ | :-------- | :-------------------------------------------- | 411 | | `isValidDate` | [args..] | 주어진 매개변수가 유효한 date인지 확인합니다. | 412 | 413 | --- 414 | 415 | ### Memoization 416 | 417 | memoization 테크닉을 이용해서 시간이 오래 걸리는 함수의 결과를 미리 저장합니다. 418 | 419 | ```js 420 | const fibonacci = (n) => (n <= 1 ? 1 : fibonacci(n - 1) + fibonacci(n - 2)); 421 | const memoizedFibonacci = memoize(fibonacci); 422 | 423 | for (let i = 0; i < 100; i++) fibonacci(30); // ~5000ms 424 | for (let i = 0; i < 100; i++) memoizedFibonacci(30); // ~50ms 425 | ``` 426 | 427 | | Function | Parameter | Description | 428 | | :-------- | :------------- | :--------------------------------- | 429 | | `memoize` | fn: `Function` | 주어진 함수의 결과를 저장해둡니다. | 430 | 431 | --- 432 | 433 | ### Curry 434 | 435 | 다중 인자를 가진 함수를 커링된 함수로 변환합니다. 436 | 437 | ```js 438 | let curriedSum = curry(sum); 439 | 440 | curriedSum(1, 2, 3); // 6 441 | curriedSum(1)(2, 3); // 6 442 | curriedSum(1)(2)(3); // 6 443 | ``` 444 | 445 | | Function | Parameter | Description | 446 | | :------- | :------------- | :------------------------ | 447 | | `curry` | fn: `Function` | 주어진 함수를 커링합니다. | 448 | 449 | --- 450 | -------------------------------------------------------------------------------- /snippets/ascending.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 평가 함수가 주어지면 오름차순으로 비교하는 함수를 반환한다. 3 | * @param {Function} fn 4 | * @returns {number} 5 | */ 6 | export const ascending = (fn) => (a, b) => { 7 | const valA = fn(a); 8 | const valB = fn(b); 9 | return valA < valB ? -1 : valA > valB ? 1 : 0; 10 | }; 11 | -------------------------------------------------------------------------------- /snippets/bifurcateBy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 주어진 리스트의 값을 두 개의 리스트으로 나눈다. 하나는 평가 함수가 참으로 평가되는 값을 포함하고 또 다른 리스트는 거짓인 값들을 포함한다. 3 | * @param {Function} predicate 4 | * @param {Array} list 5 | * @returns {Array} 6 | */ 7 | export const bifurcateBy = (predicate, list) => 8 | list.reduce( 9 | (acc, val, i) => (acc[predicate(val, i) ? 0 : 1].push(val), acc), 10 | [[], []] 11 | ); 12 | -------------------------------------------------------------------------------- /snippets/clamp.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 값이 지정된 범위 내에 있는지 확인하고, 지정된 범위에 값이 없다면 최소값과 최대값에 가장 가까운 값을 반환(클램프)한다. 3 | * @param {number} min 4 | * @param {number} max 5 | * @param {number} value 6 | * @returns {number | Error} 7 | */ 8 | export const clamp = (min, max, value) => { 9 | if (min > max) throw new Error("min cannot be greater than max"); 10 | return value < min ? min : value > max ? max : value; 11 | }; 12 | -------------------------------------------------------------------------------- /snippets/collectBy.js: -------------------------------------------------------------------------------- 1 | import groupBy from "./groupBy"; 2 | 3 | /** 4 | * @description keying-function에 따라 관련 항목을 포함하는 하위 목록을 만든다. 5 | * @param {Function} fn 6 | * @param {Array} list 7 | * @returns {Array} 8 | */ 9 | export const collectBy = (fn, list) => Object.values(groupBy(fn, list)); 10 | -------------------------------------------------------------------------------- /snippets/curry.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 다중 인자를 가진 함수를 커링합니다. 3 | * @param {Function} func 4 | * @returns {CurriedFunction} 5 | */ 6 | export const curry = (func) => { 7 | return function curried(...args) { 8 | if (args.length >= func.length) { 9 | return func.apply(this, args); 10 | } else { 11 | return function (...args2) { 12 | return curried.apply(this, args.concat(args2)); 13 | }; 14 | } 15 | }; 16 | }; 17 | -------------------------------------------------------------------------------- /snippets/descending.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 평가 함수가 주어지면 내림차순으로 비교하는 함수를 반환한다. 3 | * @param {Function} fn 4 | * @returns {number} 5 | */ 6 | export const descending = (fn) => (a, b) => { 7 | const valA = fn(b); 8 | const valB = fn(a); 9 | return valA < valB ? -1 : valA > valB ? 1 : 0; 10 | }; 11 | -------------------------------------------------------------------------------- /snippets/differenceBy.js: -------------------------------------------------------------------------------- 1 | import { indexBy } from "./indexBy"; 2 | 3 | /** 4 | * @description 첫 번째 매개변수인 리스트에서 두 번째 매개변수인 리스트에 없는 모든 항목을 찾아서 새로운 리스트를 반환한다. 5 | * @param {Function} fn 6 | * @param {Array} listA 7 | * @param {Array} listB 8 | * @returns {Array} 9 | */ 10 | export const differenceBy = (fn, listA, listB) => { 11 | const bIndex = indexBy(fn, listB); 12 | return listA.filter((val) => !bIndex[fn(val)]); 13 | }; 14 | -------------------------------------------------------------------------------- /snippets/distance.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 두 점 p1과 p2 사이의 유클리드 거리를 계산한다. 3 | * @param {Array} param0 4 | * @param {Array} param1 5 | * @returns {number} 6 | */ 7 | 8 | export const distance = ([x0, y0], [x1, y1]) => Math.hypot(x1 - x0, y1 - y0); 9 | -------------------------------------------------------------------------------- /snippets/dropWhile.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 첫 번째 요소에서부터 시작하여 조건 함수가 충족될 때까지 목록에서 요소를 삭제한다. 3 | * @param {Function} pred 4 | * @param {Array} list 5 | * @returns {Array} 6 | */ 7 | export const dropWhile = (pred, list) => { 8 | let index = 0; 9 | list.every((elem) => { 10 | index++; 11 | return pred(elem); 12 | }); 13 | return list.slice(index - 1); 14 | }; 15 | -------------------------------------------------------------------------------- /snippets/findKey.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 인덱스 내에서 주어진 조건을 만족하는 첫 번째 키를 반환한다. 3 | * @param {Function} predicate 4 | * @param {Object} index 5 | * @returns {any} 6 | */ 7 | export const findKey = (predicate, index) => 8 | Object.keys(index).find((key) => predicate(index[key], key, index)); 9 | -------------------------------------------------------------------------------- /snippets/flatten.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 중첩된 하위 리스트에서 모든 항목을 재귀적으로 가져와서 플랫 리스트를 만든다. 3 | * @param {Array} list 4 | * @returns {Array} 5 | */ 6 | export const flatten = (list) => 7 | list.reduce( 8 | (prev, next) => [ 9 | ...prev, 10 | ...(Array.isArray(next) ? flatten(next) : [next]), 11 | ], 12 | [] 13 | ); 14 | -------------------------------------------------------------------------------- /snippets/getValue.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 함수는 지정된 경로의 값을 반환하고, 값이 없으면 null을 반환한다. 3 | * @param {Object} obj 4 | * @param {string} path 5 | * @return {any | null} 6 | * 7 | */ 8 | export const getValue = (obj, path) => 9 | path 10 | .replace(/\[([^[\]]*)]/g, ".$1.") 11 | .split(".") 12 | .filter((prop) => prop !== "") 13 | .reduce( 14 | (prev, next) => (prev instanceof Object ? prev[next] : undefined), 15 | obj 16 | ); 17 | -------------------------------------------------------------------------------- /snippets/groupBy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description keying-function에 따라 개체의 관련 항목을 그룹화하고 색인화한다. 3 | * @param { Function } fn 4 | * @param { Array } list 5 | * @returns { Object } 6 | */ 7 | export const groupBy = (fn, list) => 8 | list.reduce( 9 | (prev, next) => ({ 10 | ...prev, 11 | [fn(next)]: [...(prev[fn(next)] || []), next], 12 | }), 13 | {} 14 | ); 15 | -------------------------------------------------------------------------------- /snippets/head.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 리스트의 첫 번째 요소를 가져온다. 3 | * @param {Array} list 4 | * @returns {T} 5 | */ 6 | export const head = (list) => list[0]; 7 | -------------------------------------------------------------------------------- /snippets/indexBy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description keying-function에 의해 결정된 값으로 리스트의 각 요소를 인덱싱한다. 3 | * @param {Function} fn 4 | * @param {Array} list 5 | * @returns {Object} 6 | */ 7 | export const indexBy = (fn, list) => 8 | list.reduce( 9 | (prev, next) => ({ 10 | ...prev, 11 | [fn(next)]: next, 12 | }), 13 | {} 14 | ); 15 | -------------------------------------------------------------------------------- /snippets/intersectionBy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description keying-function에 의해 정의된 대로 두 목록에 존재하는 모든 값을 찾는다. (교집합) 3 | * @param {Function} fn 4 | * @param {Array} listA 5 | * @param {Array} listB 6 | * @returns {Array} 7 | * 8 | */ 9 | export const intersectionBy = (fn, listA, listB) => { 10 | const b = new Set(listB.map(fn)); 11 | return listA.filter((val) => b.has(fn(val))); 12 | }; 13 | -------------------------------------------------------------------------------- /snippets/isValidDate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 주어진 매개변수가 유효한 date인지 확인합니다. 3 | * @param {...any} val 4 | * @returns {boolean} 5 | */ 6 | export const isValidDate = (...val) => 7 | !Number.isNaN(new Date(...val).valueOf()); 8 | -------------------------------------------------------------------------------- /snippets/isValidJSON.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 주어진 JSON 문자열이 참인지 거짓인지 판단합니다. 3 | * @param {string} str 4 | * @returns {boolean} 5 | */ 6 | export const isValidJSON = (str) => { 7 | try { 8 | JSON.parse(str); 9 | return true; 10 | } catch (e) { 11 | return false; 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /snippets/memoize.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 시간이 오래 걸리는 함수의 결과를 미리 캐싱합니다. 3 | * @param {Function} fn 4 | * @returns {any} 5 | */ 6 | export const memoize = (fn) => 7 | new Proxy(fn, { 8 | cache: new Map(), 9 | apply(target, thisArg, argsList) { 10 | let cacheKey = argsList.toString(); 11 | if (!this.cache.has(cacheKey)) 12 | this.cache.set(cacheKey, target.apply(thisArg, argsList)); 13 | return this.cache.get(cacheKey); 14 | }, 15 | }); 16 | -------------------------------------------------------------------------------- /snippets/pipe.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 왼쪽에서 오른쪽으로 함수 합성을 수행한다. 3 | * @param {Array} functions 4 | * @param {...any} args 5 | * @returns {any} 6 | */ 7 | 8 | export const pipe = (functions, ...args) => 9 | functions.reduce( 10 | (prev, next) => (Array.isArray(prev) ? next(...prev) : next(prev)), 11 | args 12 | ); 13 | -------------------------------------------------------------------------------- /snippets/recoverWith.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 주어진 함수에서 오류가 발생하면 기본값을 반환한다. 3 | * @param {any} defaultValue 4 | * @param {Function} fn 5 | * @param {...any} args 6 | * @returns {Promise} 7 | */ 8 | export const recoverWith = async (defaultValue, fn, ...args) => { 9 | try { 10 | const result = await fn(...args); 11 | return result; 12 | } catch (_e) { 13 | return defaultValue; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /snippets/sleep.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 다음 작업을 수행하기 전에 지정된 기간(밀리초)을 기다립니다. 3 | * @param {number} duration 4 | * @returns { Promise } 5 | */ 6 | export const sleep = async (duration) => 7 | new Promise((resolve) => setTimeout(resolve, duration)); 8 | -------------------------------------------------------------------------------- /snippets/sumBy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 각 요소의 개별 값을 발행하는 함수가 주어지면 리스트에 있는 모든 요소의 합을 계산한다. 3 | * @param {Function} fn 4 | * @param {Array} list 5 | * @returns {number} 6 | */ 7 | export const sumBy = (fn, list) => 8 | list.reduce((prev, next) => prev + fn(next), 0); 9 | -------------------------------------------------------------------------------- /snippets/tail.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 리스트의 첫 번째 요소를 제외한 모든 요소를 가져온다. 3 | * @param {Array} list 4 | * @returns {Array} 5 | */ 6 | export const tail = (list) => list.slice(1); 7 | --------------------------------------------------------------------------------