From d500e163f9b2ed818f0267c5bcc50a06cfcfff51 Mon Sep 17 00:00:00 2001 From: kkx7787 Date: Fri, 13 Sep 2024 00:53:50 +0900 Subject: [PATCH 1/3] Solve ex2, ex3, ex4 --- "\355\225\234\354\204\261\353\257\274/ex2.js" | 27 ++++++- "\355\225\234\354\204\261\353\257\274/ex3.js" | 20 ++++- .../ex3.test.js" | 6 +- "\355\225\234\354\204\261\353\257\274/ex4.js" | 73 ++++++++++++++++++- 4 files changed, 119 insertions(+), 7 deletions(-) diff --git "a/\355\225\234\354\204\261\353\257\274/ex2.js" "b/\355\225\234\354\204\261\353\257\274/ex2.js" index 6b95f04..3626d4a 100644 --- "a/\355\225\234\354\204\261\353\257\274/ex2.js" +++ "b/\355\225\234\354\204\261\353\257\274/ex2.js" @@ -1,4 +1,27 @@ // range 함수를 작성하세요. -const range = (start, end, step = start > end ? -1 : 1) => { }; +const range = (start, end, step = start > end ? -1 : 1) => { + const result = []; + if (start === end) return [start]; + if (end === undefined) { + step = 1; + if (start > 0) { + end = start; + start = 1; + } else if (start === 0) return [start]; + else { + end = -1; + } + } -module.exports = { range }; + if ((start < end && step === 0) || (start > end && step === 0)) return [start]; + if ((start < end && step < 0) || (start > end && step > 0)) return []; + + for (let i = start; (step > 0) ? i <= end : i >= end; i += step) { + i = Math.round(i * 10) / 10 + result.push(i); + } + + return result; +}; + +module.exports = {range}; diff --git "a/\355\225\234\354\204\261\353\257\274/ex3.js" "b/\355\225\234\354\204\261\353\257\274/ex3.js" index b1b0d75..51c82f4 100644 --- "a/\355\225\234\354\204\261\353\257\274/ex3.js" +++ "b/\355\225\234\354\204\261\353\257\274/ex3.js" @@ -1,3 +1,21 @@ Array.prototype.sortBy = function (sortProp = '') { - return this; + const props = sortProp.split(','); // 정렬 요소 split + + return this.slice().sort((a, b) => { + for (const prop of props) { + const [sortKey, order] = prop.split(':'); + const direction = order === 'desc' ? -1 : 1; + + if (a[sortKey] > b[sortKey]) return direction; + if (a[sortKey] < b[sortKey]) return -direction; + } + return 0; // 모든 정렬 기준이 동일하면 0 반환 + }); }; + +const hong = { id: 1, name: 'Hong', city: 'Busan', dept: 1 }; +const kim = { id: 2, name: 'Kim', city: 'Seoul', dept: 2 }; +const lee = { id: 3, name: 'Lee', city: 'Daegu', dept: 2 }; +const users = [lee, hong, kim]; +console.log(users.sortBy('name:desc,id:,dept:desc')); + diff --git "a/\355\225\234\354\204\261\353\257\274/ex3.test.js" "b/\355\225\234\354\204\261\353\257\274/ex3.test.js" index 6c27a4d..bc37804 100644 --- "a/\355\225\234\354\204\261\353\257\274/ex3.test.js" +++ "b/\355\225\234\354\204\261\353\257\274/ex3.test.js" @@ -8,11 +8,11 @@ const users = [lee, hong, kim]; assert.deepStrictEqual(users.sortBy('id'), [hong, kim, lee]); assert.deepStrictEqual(users.sortBy('name:desc'), [lee, kim, hong]); -assert.deepStrictEqual(users.sortBy('dept:desc,city:asc'), [hong, lee, kim]); +assert.deepStrictEqual(users.sortBy('dept:desc,city:asc'), [lee, kim, hong]); assert.deepStrictEqual(users.sortBy('dept:desc,city:desc'), [kim, lee, hong]); assert.deepStrictEqual(users.sortBy('name:desc,id:,dept:desc'), [ - kim, lee, + kim, hong, ]); -assert.deepStrictEqual(users.sortBy('dept:desc,id'), [hong, kim, lee]); +assert.deepStrictEqual(users.sortBy('dept:desc,id'), [kim, lee, hong]); \ No newline at end of file diff --git "a/\355\225\234\354\204\261\353\257\274/ex4.js" "b/\355\225\234\354\204\261\353\257\274/ex4.js" index 9ede02f..49c0d44 100644 --- "a/\355\225\234\354\204\261\353\257\274/ex4.js" +++ "b/\355\225\234\354\204\261\353\257\274/ex4.js" @@ -1,3 +1,74 @@ -function deepCopy(obj) {} +function deepCopy(obj, seen = new WeakMap()) { + if (obj === null || typeof obj !== 'object') return obj; + + if (seen.has(obj)) return seen.get(obj); // 순환 참조 방지 (WeakMap을 사용해 처리) + + let copy; + + // 배열일 경우 + if (Array.isArray(obj)) { + copy = []; + seen.set(obj, copy); // 순환 참조 방지 처리 + obj.forEach((value, index) => { + copy[index] = deepCopy(value, seen); + }); + return copy; + } + + // Set일 경우 + if (obj instanceof Set) { + copy = new Set(); + seen.set(obj, copy); + obj.forEach(value => { + copy.add(deepCopy(value, seen)); + }); + return copy; + } + + // Map일 경우 + if (obj instanceof Map) { + copy = new Map(); + seen.set(obj, copy); + obj.forEach((value, key) => { + copy.set(deepCopy(key, seen), deepCopy(value, seen)); + }); + return copy; + } + + // WeakSet은 복사하지 않음 (참조 기반이므로 복사 X) + if (obj instanceof WeakSet) { + return obj; + } + + // WeakMap도 복사하지 않음 (참조 기반이므로 복사 X) + if (obj instanceof WeakMap) { + return obj; + } + + if (obj instanceof Function) { + return obj; + } + + if (typeof obj === 'symbol') { + return Symbol(obj.description); + } + + // 일반 객체일 경우 + copy = {}; + seen.set(obj, copy); // 순환 참조 방지 처리 + + // 심볼 속성 복사 + const symKeys = Object.getOwnPropertySymbols(obj); + symKeys.forEach(sym => { + copy[sym] = deepCopy(obj[sym], seen); + }); + + // 나머지 속성 복사 + Object.keys(obj).forEach(key => { + copy[key] = deepCopy(obj[key], seen); + }); + + return copy; +} module.exports = { deepCopy }; From 29a7eef06ff00dc3c3e8271431505b22e8b7a585 Mon Sep 17 00:00:00 2001 From: kkx7787 Date: Fri, 13 Sep 2024 02:21:21 +0900 Subject: [PATCH 2/3] Refactor ex3, ex4 && Solve ex5, ex6, ex7, ex8 --- "\355\225\234\354\204\261\353\257\274/ex3.js" | 6 -- "\355\225\234\354\204\261\353\257\274/ex4.js" | 13 +--- "\355\225\234\354\204\261\353\257\274/ex5.js" | 60 ++++++++++++++++- "\355\225\234\354\204\261\353\257\274/ex6.ts" | 32 ++++++++- "\355\225\234\354\204\261\353\257\274/ex7.ts" | 65 ++++++++++++++++++- "\355\225\234\354\204\261\353\257\274/ex8.ts" | 18 ++++- 6 files changed, 170 insertions(+), 24 deletions(-) diff --git "a/\355\225\234\354\204\261\353\257\274/ex3.js" "b/\355\225\234\354\204\261\353\257\274/ex3.js" index 51c82f4..ba67f03 100644 --- "a/\355\225\234\354\204\261\353\257\274/ex3.js" +++ "b/\355\225\234\354\204\261\353\257\274/ex3.js" @@ -13,9 +13,3 @@ Array.prototype.sortBy = function (sortProp = '') { }); }; -const hong = { id: 1, name: 'Hong', city: 'Busan', dept: 1 }; -const kim = { id: 2, name: 'Kim', city: 'Seoul', dept: 2 }; -const lee = { id: 3, name: 'Lee', city: 'Daegu', dept: 2 }; -const users = [lee, hong, kim]; -console.log(users.sortBy('name:desc,id:,dept:desc')); - diff --git "a/\355\225\234\354\204\261\353\257\274/ex4.js" "b/\355\225\234\354\204\261\353\257\274/ex4.js" index 49c0d44..45543e3 100644 --- "a/\355\225\234\354\204\261\353\257\274/ex4.js" +++ "b/\355\225\234\354\204\261\353\257\274/ex4.js" @@ -35,17 +35,8 @@ function deepCopy(obj, seen = new WeakMap()) { return copy; } - // WeakSet은 복사하지 않음 (참조 기반이므로 복사 X) - if (obj instanceof WeakSet) { - return obj; - } - - // WeakMap도 복사하지 않음 (참조 기반이므로 복사 X) - if (obj instanceof WeakMap) { - return obj; - } - - if (obj instanceof Function) { + // 참조 기반인 WeakSet, WeakMap, 함수는 그대로 반환 + if (obj instanceof WeakSet || obj instanceof WeakMap || typeof obj === 'function') { return obj; } diff --git "a/\355\225\234\354\204\261\353\257\274/ex5.js" "b/\355\225\234\354\204\261\353\257\274/ex5.js" index 464a05a..4863f65 100644 --- "a/\355\225\234\354\204\261\353\257\274/ex5.js" +++ "b/\355\225\234\354\204\261\353\257\274/ex5.js" @@ -1,3 +1,61 @@ module.exports = { - searchByKoreanInitialSound: (data, firstSounds) => {}, + searchByKoreanInitialSound: (data, firstSounds) => { + return data.filter((str) => str.match(getRegExp(firstSounds))); + }, }; +const INITIAL = [ + "ㄱ", + "ㄲ", + "ㄴ", + "ㄷ", + "ㄸ", + "ㄹ", + "ㅁ", + "ㅂ", + "ㅃ", + "ㅅ", + "ㅆ", + "ㅇ", + "ㅈ", + "ㅉ", + "ㅊ", + "ㅋ", + "ㅌ", + "ㅍ", + "ㅎ", +]; +const INITIAL_RANGE = [ + "가-깋", + "까-낗", + "나-닣", + "다-딯", + "따-띻", + "라-맇", + "마-밓", + "바-빟", + "빠-삫", + "사-싷", + "싸-앃", + "아-잏", + "자-짛", + "짜-찧", + "차-칳", + "카-킿", + "타-팋", + "파-핗", + "하-힣", +]; + +const initialMap = new Map(); +INITIAL.forEach((initial, index) => { + initialMap.set(initial, INITIAL_RANGE[index]); +}); + +function getRegExp(initials) { + return new RegExp( + initials + .split("") + .map((initial) => `[${initialMap.get(initial) || initial}]`) // 초성이 있으면 매핑된 범위를 사용, 없으면 그대로 사용 + .join("") // 각각의 범위를 이어붙임 + ); +} \ No newline at end of file diff --git "a/\355\225\234\354\204\261\353\257\274/ex6.ts" "b/\355\225\234\354\204\261\353\257\274/ex6.ts" index 424ca54..be05904 100644 --- "a/\355\225\234\354\204\261\353\257\274/ex6.ts" +++ "b/\355\225\234\354\204\261\353\257\274/ex6.ts" @@ -1,4 +1,32 @@ export const randTime = (val: T): Promise => - new Promise(resolve => setTimeout(resolve, Math.random() * 1000, val)); + new Promise(resolve => setTimeout(resolve, Math.random() * 1000, val)); -export function promiseAllSettled(promises: Promise[]) {} +// 각 promise 결과 타입 정의 +type FulfilledResult = { status: 'fulfilled'; value: T }; +type RejectedResult = { status: 'rejected'; reason: String }; + +// promiseAllSettled 반환 결과 타입 정의 +type PromiseAllSettledResult = FulfilledResult | RejectedResult; + +export function promiseAllSettled(promises: Promise[]): Promise[]> { + return new Promise((resolve) => { + const results: PromiseAllSettledResult[] = []; + let completedCount = 0; + + promises.forEach((promise, index) => { + promise + .then((value) => { + results[index] = { status: 'fulfilled', value: value }; + }) + .catch((reason) => { + results[index] = { status: 'rejected', reason: reason }; + }) + .finally(() => { + completedCount += 1; + if (completedCount === promises.length) { + resolve(results); + } + }); + }); + }); +} \ No newline at end of file diff --git "a/\355\225\234\354\204\261\353\257\274/ex7.ts" "b/\355\225\234\354\204\261\353\257\274/ex7.ts" index 62812ac..95a0342 100644 --- "a/\355\225\234\354\204\261\353\257\274/ex7.ts" +++ "b/\355\225\234\354\204\261\353\257\274/ex7.ts" @@ -1,3 +1,66 @@ const POST_URL = 'https://jsonplaceholder.typicode.com/posts'; -export async function getPosts(userId: number | string) {} +export type CommentResponse = { + postId: number; + id: number; + name: string; + email: string; + body: string; +}; + +export type Comment = { + postId: number; + id: number; + email: string; + body: string; +}; + +export type Post = { + postId: number; + title: string; + comments?: Comment[]; +}; + +export type UserPost = { + postId: number; + id: number; + title: string; + body: string; +}; + +// fetch 함수 분리 +async function fetchJson(url: string): Promise { + const response = await fetch(url, { method: "GET" }); + if (!response.ok) { + throw new Error(`Failed to fetch from ${url}: ${response.statusText}`); + } + return await response.json() as T; +} + +export async function getPosts(userId: number | string): Promise { + const resList = await fetchJson(`${POST_URL}?userId=${userId}`); + + // 각 게시글에 대한 댓글을 가져오고, Post 객체를 생성하는 작업 + const postsByUserID = await Promise.all( + resList.map(async (res) => { + const commentSeries = await fetchJson(`${POST_URL}/${res.id}/comments`); + + // 댓글 데이터를 Comment로 변환 + const comments = commentSeries.map((comment) => ({ + postId: comment.postId, + id: comment.id, + email: comment.email, + body: comment.body + })); + + // Post 객체 생성 + return { + postId: res.id, + title: res.title, + comments: comments, + } as Post; + }) + ); + + return postsByUserID; +} \ No newline at end of file diff --git "a/\355\225\234\354\204\261\353\257\274/ex8.ts" "b/\355\225\234\354\204\261\353\257\274/ex8.ts" index a67a2d2..906b704 100644 --- "a/\355\225\234\354\204\261\353\257\274/ex8.ts" +++ "b/\355\225\234\354\204\261\353\257\274/ex8.ts" @@ -1,8 +1,20 @@ // dummy(mock)입니다. 올바르게 수정하세요. -const debounce = (cb: any, delay: number) => (i: number) => {}; -const throttle = (cb: any, delay: number) => (i: number) => {}; -// function throttle... +let timer: number | NodeJS.Timeout; +timer=0; +const debounce = (cb: any, delay: number) => (i: number) => { + clearTimeout(timer); + timer = setTimeout(()=>cb(i), delay); +}; + +let isCalled: Boolean; +const throttle = (cb: any, delay: number) => (i: number) => { + if(!isCalled){ + cb(i); + isCalled = true; + setTimeout(()=>{isCalled = false}, delay); + } +}; const debo = debounce((a: number) => console.log(a + 1), 500); for (let i = 10; i < 15; i++) debo(i); // 15 출력 From 88d2722497de729643230d1ba5c2cf4e82dd51c1 Mon Sep 17 00:00:00 2001 From: kkx7787 Date: Fri, 13 Sep 2024 06:20:43 +0900 Subject: [PATCH 3/3] Implement ex1 --- package.json | 10 +- .../ex1/book-edit.html" | 70 ++++++++ .../ex1/index.html" | 151 ++++++++++++++++++ .../ex1/register.html" | 77 +++++++++ .../ex1/src/input.css" | 3 + .../ex1/tailwind.config.js" | 8 + 6 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 "\355\225\234\354\204\261\353\257\274/ex1/src/input.css" create mode 100644 "\355\225\234\354\204\261\353\257\274/ex1/tailwind.config.js" diff --git a/package.json b/package.json index c356ea8..7c4f8e3 100644 --- a/package.json +++ b/package.json @@ -11,5 +11,13 @@ "TS" ], "author": "indiflex", - "license": "ISC" + "license": "ISC", + "devDependencies": { + "tailwindcss": "^3.4.11", + "ts-node": "^10.9.2", + "typescript": "^5.6.2" + }, + "dependencies": { + "@types/node": "^22.5.4" + } } diff --git "a/\355\225\234\354\204\261\353\257\274/ex1/book-edit.html" "b/\355\225\234\354\204\261\353\257\274/ex1/book-edit.html" index e69de29..1a59e09 100644 --- "a/\355\225\234\354\204\261\353\257\274/ex1/book-edit.html" +++ "b/\355\225\234\354\204\261\353\257\274/ex1/book-edit.html" @@ -0,0 +1,70 @@ + + + + + + Document + + + + + + +
+ +
+
+ +

BookMark

+
+
+ + + + +
+
+ +
+ +

Bookmarks

+
+
+ ⓒ Hanaro 2024 +
+
+ + \ No newline at end of file diff --git "a/\355\225\234\354\204\261\353\257\274/ex1/index.html" "b/\355\225\234\354\204\261\353\257\274/ex1/index.html" index e69de29..4cc53e7 100644 --- "a/\355\225\234\354\204\261\353\257\274/ex1/index.html" +++ "b/\355\225\234\354\204\261\353\257\274/ex1/index.html" @@ -0,0 +1,151 @@ + + + + + + Document + + + + + + +
+ +
+
+ +

BookMark

+
+
+ + + +
+ + +
+
+
+ + +
+ + + + + + + +
+
+ ⓒ Hanaro 2024 +
+
+ + \ No newline at end of file diff --git "a/\355\225\234\354\204\261\353\257\274/ex1/register.html" "b/\355\225\234\354\204\261\353\257\274/ex1/register.html" index e69de29..493a64c 100644 --- "a/\355\225\234\354\204\261\353\257\274/ex1/register.html" +++ "b/\355\225\234\354\204\261\353\257\274/ex1/register.html" @@ -0,0 +1,77 @@ + + + + + + Document + + + + + + +
+ +
+
+ +

BookMark

+
+
+ + + + + +
+ + +
+
+
+ + +
+
+ +

Sign Up

+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ +
+
+
+ +
+ + \ No newline at end of file diff --git "a/\355\225\234\354\204\261\353\257\274/ex1/src/input.css" "b/\355\225\234\354\204\261\353\257\274/ex1/src/input.css" new file mode 100644 index 0000000..bd6213e --- /dev/null +++ "b/\355\225\234\354\204\261\353\257\274/ex1/src/input.css" @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; \ No newline at end of file diff --git "a/\355\225\234\354\204\261\353\257\274/ex1/tailwind.config.js" "b/\355\225\234\354\204\261\353\257\274/ex1/tailwind.config.js" new file mode 100644 index 0000000..7cac5aa --- /dev/null +++ "b/\355\225\234\354\204\261\353\257\274/ex1/tailwind.config.js" @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ["./src/**/*.{html,js}"], + theme: { + extend: {}, + }, + plugins: [], +} \ No newline at end of file