27일차, 재귀함수 stringify, DOM작성
2021. 08. 25 수요일
1. Today's Key points!🔑
- 재귀함수
- JSON, stringify
- DOM
2. 정리해보자!🧹
26일차에 이어 재귀함수에 익숙해지는 시간을 가질 수 있었다.
JSON이란? JSON은 JavaScript Object Notation의 줄임말로, 데이터 교환을 위해 만들어진 객체 형태의 포맷이다. 예를 들자면, 한국인과 프랑스인이 있는데, 이 둘이 소통하려면 어떻게 해야할까? 영어로 소통하면 된다! 영어는 전세계적으로 공통적으로 사용하는 언어이기 때문이다. 그럼 컴퓨터안에서는 JSON으로 소통을 하는 것이다. 네트워크를 통해, 어떤 객체 내용을 다른 프로그램에게 전송한다고 가정해 보겠다. 각자 언어로 쓴 코드를 다른 프로그램에게 보내면 읽지 못할 것이다. 그래서 JSON을 사용해서 범용적으로 읽을 수 있는 형태로 바꿔줘서 서로 다른 프로그램 끼리 데이터를 주고 받을 수 있게 해준다.
그럼 어떻게 바꿔주나? JSON.stringify(object)를 사용해주면 된다. 예를 들어, message 객체가 있다고 해보자.
1
2
3
4
5
6
|
const message = {
sender: "김사장",
receiver: "박사장",
message: "박사장 오늘 저녁 같이 먹을래?",
createdAt: "2021-01-12 10:10:10"
}
|
cs |
이것을 JSON.stringify(message) 해주면
1
2
|
let transferableMessage = JSON.stringify(message)
console.log(transferableMessage) // `{"sender":"김사장","receiver":"박사장","message":"박사장 오늘 저녁 같이 먹을래?","createdAt":"2021-01-12 10:10:10"}`
|
cs |
콘솔로그에 결과처럼 저런 형태로 바뀌게 된다.
그럼 반대의 상황은 어떻게 해주는가? JSON.parse(object) 해주면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
|
let transferableMessage = `{"sender":"김코딩","receiver":"박해커","message":"해커야 오늘 저녁 같이 먹을래?","createdAt":"2021-01-12 10:10:10"}`
let obj = JSON.parse(transferableMessage)
console.log(obj)
/*
* {
* sender: "김코딩",
* receiver: "박해커",
* message: "해커야 오늘 저녁 같이 먹을래?",
* createdAt: "2021-01-12 10:10:10"
* }
*/
|
cs |
JSON의 기본 규칙
JSON을 얼핏 보기에 자바스크립트의 객체와 별반 다를 바가 없어 보이지만, 자바스크립트의 객체와는 미묘하게 다른 규칙이 있다.
자바스크립트 객체JSON
키 | 키는 따옴표 없이 쓸 수 있음 | 반드시 큰따옴표를 붙여야 함 |
문자열 값 | 문자열 값은 어떠한 형태의 따옴표도 사용 가능 | 반드시 큰따옴표로 감싸야 함 |
또한 JSON은 키와 값 사이, 그리고 키-값 쌍 사이에는 공백이 있어서는 안된다.
3. Sprint 복기!🧐
두 가지 Sprint를 진행했다. JSON.stringify를 직접 구현해보는 것과 DOM작성하는 것이었다.
이 스프린트를 진행해보면서 재귀함수에 익숙해지는 시간을 가질 수 있었고, 재귀함수를 너무 어렵게만 생각하면 오히려 생각이 잠길 수 있다는 것을 알았다. 재귀함수를 사용할 때, 반복되고있는 것이 무엇인지를 파악하고 가장 작은 단위가 무엇인지를 생각해서 종료시점을 만들어주면 된다.
그럼 첫 번째 과제를 복기해보겠다. 모든 타입을 String화 해야하는데, JSON.stringify 형태로 만들어 주어야한다.
9(숫자형태) -> '9' / null -> 'null' / true(boolean형태) -> 'true' / 'abc'(문자열) -> '"abc"' / [1, 2, 'a'] -> '[1, 2, 'a']' / { a : 1, b : 2, c : 'c' } -> '{"a":1,"b":2,"c":"c"}'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
function stringifyJSON(obj) {
if(typeof obj === 'number') return `${obj}`;
if(typeof obj === 'string') return `"${obj}"`;
if(typeof obj === 'boolean') return `${obj}`;
if(typeof obj === 'object'){
if(obj === null) { // typeof null을 해보면 'object'가 나오기 때문에 'object'안에서 처리해주었다.
return 'null';
}
if(Array.isArray(obj)){ //[value, value, value] 배열은 결국 요소(value)가 반복되기 때문에 저 부분을 재귀함수 처리해주면 된다.
let result = ''; // 빈 문자열을 만들고
for(let i = 0; i < obj.length; i++){ // 반복문으로
result = result + stringifyJSON(obj[i]) +','; // result에 계속 더해준다.
}
return '[' + result.slice(0, -1) + ']'; // slice를 해주는 이유는 마지막의 , 를 지우기 위해서
}
else { // object 일 경우 배열과 마찬가지로 해주는데, 객체는 결국 key와 value가 반복된다. {key : value, key : value, key: value}
let result = '';
for(key in obj){
if(typeof obj[key] === 'function' || obj[key] === undefined) continue; // 이 부분은 JSON.stringify 특성상 함수와 undefined는 아무것도 표시하지 않기 때문에 그 처리를 해준 것이다.
result = result + `${stringifyJSON(key)}:${stringifyJSON(obj[key])},`;
}
return '{' + result.slice(0, -1) + '}';
}
}
};//
|
cs |
사실 이 부분을 정규 시간에 다 풀지 못했다. 문제를 잘 이해 못한 것도 있고, 재귀함수를 언제 써줘야하는지를 몰라서 헤매고 있었는데, 강의를 듣고 좀 허무했다. 생각보다 너무 간단해서.. 강의를 듣고 나서 신기하게 바로 써졌다. 내가 너무 재귀함수를 복잡하게 생각하고 있었던 것 같다. 조금은 단순하게 생각해볼 필요가 있는 것 같다.
그리고 다음은 DOM을 작성하는 것이다. 아래와 같은 결과를 만들어야 한다.
처음부터 바로 재귀를 사용해서 위 처럼 구현하는 것은 불가능 했다. 그래서 반복문을 사용해서 위 처럼 구현해보고, 그 반복문을 계속 뚫어져라 쳐다보면서 재귀를 어떻게 써주면 좋을지 고민하면서 풀었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
const root = document.getElementById('root');
function createTreeView(menu, currentNode) {
// for(let i = 0; i < menu.length; i++){
// const li = document.createElement('li');
// currentNode.appendChild(li);
// const checkbox = document.createElement('input');
// li.appendChild(checkbox);
// checkbox.setAttribute('type', 'checkbox');
// const name = document.createElement('span');
// li.appendChild(name);
// name.textContent = menu[i].name;
// const ul = document.createElement('ul');
// for(let j = 0; j < menu[i].children.length; j++){
// li.appendChild(ul);
// const li2 = document.createElement('li');
// ul.appendChild(li2);
// const checkbox2 = document.createElement('input');
// li2.appendChild(checkbox2);
// checkbox2.setAttribute('type', 'checkbox');
// const name2 = document.createElement('span');
// li2.appendChild(name2);
// name2.textContent = menu[i].children[j].name;
// return createTreeView(menu[i].children, ul);
// const ul2 = document.createElement('ul');
// for(let k = 0; k < menu[i].children[j].children.length; k++){
// li2.appendChild(ul2);
// const li3 = document.createElement('li');
// ul2.appendChild(li3);
// li3.textContent = menu[i].children[j].children[k].name;
// }
// }
// }
for(el of menu){
if(!('children' in el)){
const li2 = document.createElement('li');
currentNode.appendChild(li2);
li2.textContent = el.name;
}
if('children' in el){
const li = document.createElement('li');
currentNode.appendChild(li);
const checkbox = document.createElement('input');
li.appendChild(checkbox);
checkbox.setAttribute('type', 'checkbox');
const name = document.createElement('span');
li.appendChild(name);
name.textContent = el.name;
const ul = document.createElement('ul');
li.appendChild(ul);
createTreeView(el.children, ul);//재귀함수
}
}
}
|
cs |
주석처리 되어있는 부분은 처음에 메뉴판을 구현하기 위해서 for문만 사용해서 만들어보았다. 근데 저 for문만으로 만든것도 완벽하게 문제를 풀지는 못했다. children이 없는 부분을 처리를 못해줬다.
이제 주석 밑의 for문 안의 첫 조건은 가장 작은 단위를 처리해준 것이다. 객체에 children 속성이 없으면 span, checkbox없이 나타내야 했고 가장 안쪽 부분에 나타나야 하는 것이기 때문에 일종의 Base Case인 셈이다. 그리고 아랫 부분이 Recursive Case가 된다. 저 html의 구조를 살펴보면 ul > li+checbox+span 이 반복되고, children이 없으면 ul > li 가 끝이다.
어떻게 하면 저 구조를 만들어 줄 수 있을지 하드코딩도 해보고, 이것저것 다해보면서 마지막에 작성한 코드가 위의 코드인데 테스트가 통과가 확 되니까 그 성취감이 밀려왔다. 이게 다 하고나서 다시 보니까 뭔가 별거 없어보이긴 하는데, 나중에 다시 싹 밀고 한번 더 해봐야겠다.
'코드스테이츠 수강 TIL > Section 2' 카테고리의 다른 글
30일차, underbar (0) | 2021.08.30 |
---|---|
29일차, Graph, Tree (0) | 2021.08.28 |
28일차, Stack Queue (0) | 2021.08.27 |
26일차, 재귀함수 (0) | 2021.08.25 |
25일차, 객체지향 프로그래밍 (0) | 2021.08.23 |