내일부터의 나를 예언하는 짤
이번 주차는 다른 코딩언어와 겹치는 부분이 있어서 새롭게 알게된 부분만 집중적으로 노트했다.
DOM
Document Object Modeling (DOM): HTML (Document)파일을 JS가 해석할 수 있는 Object의 형태로 Modeling하는 것.
Js로 접근과 제어를 할 수 있다.
getElementById(), getElementsByTagName() 등의 메서드로 접근이 가능하다.innerText, attribute, style등의 속성(property)를 바꿀 수 있다.Class란
개발자가 직접 만들 수 있는 객체로 class 키워드를 사용한 일종의 탬플릿이라고 볼 수 있다.
class Potato {
constructor(breed, harvestYear) {
this._breed = breed;
this._harvestYear = harvestYear;
}
}
위의 코드처럼 constructor를 사용하여 instance를 만들 수 있고 필요한 매개변수를 받아올 수 있다. 여기서 this는 객체 클라스 전체가 아닌
Class의 속성에 접근하기 위해서는 getter와 setter를 사용할 수 있다. setting을 할 때 내부에서 검증을 거칠 수도 있다. 문법은 아래의 코드와 같다.
class Potato {
constructor(breed, harvestYear) {
this._breed = breed;
this._harvestYear = harvestYear;
}
get breed () {
return this._breed;
}
set breed (value) {
// 문자열 검증
if (typeof value !== 'string') {
console.log(`[오류] 감자의 종자가 문자열이 아닙니다`);
return;
}
this._breed = value;
}
get harvestYear(values) {
return this._harvestYear;
}
set harvestYear (value) {
// 연도 검증
if (value.length !== 4) {
console.log(`[오류] 감자 수확 연도가 유효하지 않습니다.`);
return;
}
// 변환
this._harvestYear = value;
}
}
이때 _를 속성 앞에 붙여주지 않으면 콜스택이 무한루프가 생길 수 있다.

>>call stack size exceeded: 재귀적 함수처럼 실행되는 getter 혹은 setter의 무한루프가 생긴 경우 일 수 있음
그리고 다른 코딩 언어처럼 inheritance가 존재하는데 사용법은 아래와 같다.
class Potato {
// 생성자랑 getters, setters
// 코드 부분
}
class SweetPotato extends Potato {
// constructor가 부모와 동일시 생략 가능
// 아래와 같이 살짝 다르다면
constructor (breed, harvestYear, sweetness) {
super(breed, harvestYear);
this._sweetness = sweetness;
}
// overriding 가능
// 새로운 메서드 생성 가능
}
마지막으로 static을 하숑하여 class 레벨의 메서드를 정의할 수 있다.
class Calculator {
static add(a, b) {
return a + b;
}
static subtract(a, b) {
return a - b;
}
}
// 인스턴스 생성 필요 없이 사용 가능
console.log(Calculator.add(1, 2)); // 3
console.log(Calculator.subtract(3, 2)); // 1
Closure
먼저 렉시컬 스코프(lexical scope)란 "외부 렉시컬 환경에 대한 참조"로 3주차 강의 때새로 배운 개념이다.
클로저는 렉시컬 스코프와 관련이 있는데 아래의 코드로 설명하자면
// 외부 함수보다 중접 함수가 더 오래 유지되는 경우
// 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를
// (여전히)!! 참조할 수 있다. ← 이 개념에서 중첩 함수가 바로 클로저
const x = 1;
// 1
function outer() {
const x = 10;
const inner = function () {
console.log(x);
};
return inner;
}
// outer 함수 실행한 것을 innerFunc에 담음
const innerFunc = outer();
// 윗줄과 동일
// const innerFunc = function () {
// console.log(x);
// };
// ------------이곳에서 outer 함수의 실행 컨택스트는...
// ...이미 사라짐
// BUT!!
// 여전히 우리는 outer의 x를 참조할 수 있다
// 이것이 바로 Closure
innerFunc();
위 코드에서 innerFunc()는 outer()의 중첩함수이지만 outer가 실행된 이후에도 남아있어서 이미 콜스택에서 outer의 정보가 사라졌음에도 outer 내부의 x를 참조할 수 있다.
이 현상의 원인은 garbage collector가 참조가 0인 코드만, 즉 참조하지 않는 부분만 수거해 가는데, 위의 경우에서는 inner가 outer의 부분을 여전히 참조하고 있다고 판단이 되므로 outer의 lexical scope가 남아있게 되는 것
이 어려운 개념이 closure이다.

명심하자, 중첩함수가 외부 함수보다 오래 유지될때만 여전히!! 참조가 가능
오늘은 문제풀이도 풀이지만 알고리즘을 앞으로 어떻게 공부해야하는지에 대해 집중한 시간이었다. 몇가지 습관을 들이면 좋을 것 같은 공부법들을 나열해보겠다.
1. 직접 테스트케이스 만들어보기
코테를 보다보면 예시 케이스를 한개만 주거나 예시 케이스 외에 채점이 불가능한 방식을 사용하는 곳이 있다고 한다. 이런 경우에 대비해 스스로가 직접 테스트 케이스를 만들어서 예상 답안까지 돌려보는 연습이 필요하다.
2. 제약사항 대비하기
코테를 하는 동안에는 다양한 제약사항이 있을 수 있다. 이 때문에 평소에 풀던 환경을 완벽히 재현해서 문제를 풀기는 어려울 수 있다. 따라서 조금씩 스스로에게 제약을 두거나 제약사항에 익숙해지는 기간을 코테에 초대 받았을때 준비하는 연습이 필요하다.
실제 있었던 제약사항이라고 한다.
3. 노트하기
지금이야 막 공부를 시작한 단계이기 때문에 새로 배운 내용이 잘 떠오를 수는 있지만, 시간이 지나고 처음에 사용했던 메소드들이 기억이 안 나는 경우가 생길 수 있다. 이런 때를 대비하여 노트를 작성하는 습관을 들여야한다. 적으면 좋은 내용들은 아래와 같다.
4. 꾸준함
문제풀이 방식을 꾸준히 기록해두는 것도 좋고, 꾸준히 복습을 하는 것도 좋다. 나만의 학습법을 익혀서 꾸준히 하는 것이 결국 답이라고 생각한다. 사람마다 맞는 공부법이 다르기에 정답이 있는 것은 아니지만 어느 방법이든 꾸준함이 유지 되어야 한다고 생각한다.
아래는 꾸준히 푼 알고리즘 문제를 깃허브에 올린 사례이다.
GitHub: JeongHwan-dev/algorithm-solving-with-js
내일부터 개인 프로젝트에 집중하는 기간으로 심히 걱정된다. 아마도 썸네일 같은 상황이 자주 생기지 않을까 싶다.