1. 1주차 핵심 개념
자바스크립트의 기본기가 탄탄해야 프론트엔드 프레임워크를 사용했을 때, 다양한 상황에 따른 문제 해결력을 보여줄 수 있다. 경험상 주니어 레벨에서의 겪는 대부분의 문제는 본인이 사용하고 있는 언어와 기술에 대한 낮은 이해도로 인해 발생하기 때문이다. 본인은 1주차에 학습한 개념 중 중요한 부분, 다시 한 번 되짚고 싶은 부분 위주로 작성했다.
- 1.1 호이스팅
var 키워드는 선언과 초기화 단계가 동시에 진행되므로 코드 실행흐름 도달 이전에 참조시 undefined가 출력됨.
let과 const는 선언과 초기화 단계가 분리되어 진행됨. 즉, 소스코드 평가단계에서 식별자 정보 등록 후 undefined 초기화는 수행하지 않으므로 실행 단계에서 변수 선언문이 실행될 때 참조가 가능하고 이전에 참조시 참조 에러가 발생함. 에러가 발생하는 영역을 TDZ라고 부른다. 함수도 호이스팅이 발생하는데, 함수는 undefined가 아닌 함수 객체로 평가되기 때문에 정상적인 함수의 호출이 가능하다.
단, 함수 표현식의 경우 변수 호이스팅과 동일하게 평가되므로, var는 undefined 이며, let const 함수 표현식의 경우 referenceError 발생
- 1.2 클래스
// 생성자 함수는 객체(인스턴스)를 생성하는 함수
// 매개 변수를 전달받아 인스턴스의 프로퍼티에 value를 할당할 수 있음.
// 생성자 함수로 인스턴스를 생성할 때 new 키워드를 사용한다.
// 생성자 함수는 파스칼 케이스로 네이밍한다.
function Shape(width, height) {
this.width = width;
this.height = height;
// this.getArea = function () {
// return this.width * this.height;
// };
}
// 자바스크립트의 모든 객체는 자신의 부모격 역할을 하는 객체가 존재한다. 이를 프로토타입 또는 프로토타입 객체라 한다.
// 이를 통해 특정 생성자 함수로 생성된 인스턴스는 공통 속성과 메서드를 상속할 수 있다.
// 생성자함수.prototype 과 인스턴스.__proto__는 동일하다.
// prototype 객체의 __proto__ 접근자 프로퍼티를 이용해 프토토타입 체인을 따라가면 최상위는 Object.prototype이 존재한다.
// 주의할 점은 인스턴스의 __proto__를 통해 메서드에 접근할 경우 내부적으로 this 키워드를 참조하고 있을 경우에 this 바인딩은 Shape 생성자로 생성된
// 인스턴스가 아닌 프로토타입 객체를 가리키게 된다.
Shape.prototype.getArea = function () {
return this.width * this.height;
}
const rect1 = new Shape(10, 10);
console.log(rect1.getArea());
console.log(rect1.__proto__.getArea());
/*
코드 내에서 __proto__ 접근자 프로퍼티를 직접 사용하는 것은 권장하지 않는다.
모든 객체가 __proto__ 접근자 프로퍼티를 사용할 수 있는 것은 아니기 때문이다.
__proto__ 접근자 프로퍼티 대신 프로토타입의 참조를 취득하고 싶은 경우에는 Object.getPrototypeOf 메서드를 사용하고,
프로토타입을 교체하고 싶은 경우에는 Object.setPrototypeOf 메서드를 사용할 것을 권장
*/
class Custom {
static test() {
console.log("나는 정적 메서드임");
}
test() {
console.log("나는 메서드임");
}
}
console.log(Custom.test());
console.log(new Custom().test());
- 1.2.1 es5 생성자 함수에서의 상속 구현하기
// es5 생성자 함수에서의 상속 구현하기
function Shape(color) {
this.color = color;
this.getColor = function () {
return this.color;
}
}
function Rectangle(color, width, height) {
Shape.call(this, color);
this.width = width;
this.height = height;
this.getArea = function () {
return this.width * this.height;
}
}
const rect1 = new Rectangle("red", 10, 20);
console.log(rect1.getColor());
- 1.3 Promise
// 비동기를 처리결과 순서를 보장하기 위해 발생한 콜백지옥을 해결하기 위해 프로미스를 사용할 수 있다.
// resolve를 호출하면 비동기 처리에 성공했다는 fulfilled로 reject를 호출하면 비동기 처리에 실패했다는 rejected 상태로 변경된다.
// 비동기 처리결과를 받기 위해 후속처리 메서드를 사용하고 성공 결과값은 then, 실패 결과값은 catch로 핸들링한다.
// 후속처리 메서드는 promise를 반환하기 때문에 메서드 체이닝이 가능하다.
function task1() {
return new Promise((resolve) => {
console.log("task1");
resolve();
});
}
function task2() {
return new Promise((resolve) => {
console.log("task2");
resolve();
});
}
function task3() {
return new Promise((resolve) => {
console.log("task3");
resolve();
});
}
function task4() {
return new Promise((resolve) => {
console.log("task4");
resolve();
});
}
task1().then(() => {
console.log("task1 done");
task2().then(() => {
console.log("task2 done");
task3().then(() => {
console.log("task3 done");
task4().then(() => {
console.log("task4 done");
console.log("done");
});
});
});
});
task1()
.then(() => task2())
.then(() => task3())
.then(() => task4())
.then(() => console.log("done"));
// task1()
// .then(() => task2())
// .then(() => task3())
// .then(() => task4())
// .then(() => console.log("done"));
- 1.4 async / await
/*
Async/Await는 비동기 코드를 마치 동기적인 흐름으로 작성할 수 있습니다.
async 함수에서 await를 사용하면 해당 프로미스 처리 결과를 받기 전까지 함수의 실행을 일시적으로 중단합니다.
try catch 블록을 사용하여 보다 쉽게 에러 핸들링이 가능합니다.
*/
export const sleep = (ms) => new Promise((res) => setTimeout(res, ms));
async function getApple() {
await sleep(4000);
return "🍎"
}
async function getBanana() {
await sleep(2000);
return "🍌"
}
async function pickFruits() {
// 아래의 방법은 Promise.all을 사용하지 않아도 비동기 코드를 병렬 실행할 수 있다.
const applePromise = getApple();
const bananaPromise = getBanana();
const apple = await applePromise;
const banana = await bananaPromise;
console.log(apple, banana);
}
pickFruits();
- 1.5 closure
/*
클로저는 중첩된 내부함수가 반환된 이후에도 자신이 선언되었을 당시의 렉시컬 환경을 기억하여
외부 함수의 변수(자유 변수)에 접근할 수 있는 개념을 말한다.
클로저는 외부에서 접근할 수 없도록 데이터 은닉에 목적이 있다.
*/
function Counter() {
// 카운트를 유지하기 위한 자유 변수
var counter = 0;
// 클로저
this.increase = function () {
return ++counter;
};
// 클로저
this.decrease = function () {
return --counter;
};
}
- 1.6 실행 컨텍스트
자바스크립트 엔진은 먼저 전역 코드를 평가하여 전역 실행 컨텍스를 생성하고, 함수가 호출되면 함수 코드를 평가하여 함수 실행 컨텍스트를 생성한다. 이때 생성된 컨텍스트는 스택 자료구조로 관리된다. 이를 실행 컨텍스트 스택이라고 한다.
실행 컨텍스트 스택은 코드의 실행 순서를 관리한다.실행 컨텍스트 스택의 최상위에 존재하는 실행 컨텍스트는 언제나 현재 실행 중인 코드의 실행 컨텍스트다. 이 실행 컨텍스트를 실행 중인 실행 컨텍스트(running execution context)라고 부른다.
렉시컬 환경(LexicalEnvironment)은 식별자와 식별자에 바인딩된 값, 그리고 상위 스코프에 대한 참조를 기록하는 자료구조로 실행 컨텍스트를 구성하는 컴포넌트이다.
렉시컬 환경은 키와 값을 갖는 객체 형태의 스코프(전역, 함수, 블록 스코프)를 생성하여 식별자를 키로 등록하고 식별자에 바인딩된 값을 관리한다.
최초에 전역 코드가 평가되면 전역 실행 컨텍스를 생성하고 컨텍스트 스택에 푸시 -> 이후 전역 코드가 실행되고 함수를 만나면 함수를 실행해 함수 실행 컨텍스트를 생성함
- 렉시컬 환경의 구성요소
1. 환경 레코드(Environment Record): 식별자와 식별자에 바인딩된 값을 관리하는 저장소
2. 외부 렉시컬 환경에 대한 참조(Outer Lexical Environment Ref): 외부 렉시컬 환경에 대한 참조는 상위 스코프를 가리킨다.
2. 회고
Keep
프로젝트 캠프 이전에 모던 자바스크립트 딥다이브 도서로 1회독 스터디를 진행했던 경험이 있어, 1주차의 자바스크립트 개념을 학습하는데 문제없었다. 조금 희미해졌던 개념들을 다시 한 번 상기시킬 수 있었던 유익한 시간이었다.
Problem
1회독을 했음에도 당시에 어려웠던 부분은 참고자료를 찾아보며 머리와 시간을 써야했다.
Try
1. 과거에도 다짐했지만, 다시 한 번 다짐한다. 쉽진 않겠지만 딥다이브 2회독.. 가보자고
2. Next.js를 위한 복습(next-auth 라이브러리, middleware.js, tanstack-query)
참고
https://m.yes24.com/Goods/Detail/92742567
본 후기는 본 후기는 [유데미x스나이퍼팩토리] 프로젝트 캠프 : Next.js 1기 과정(B-log) 리뷰로 작성 되었습니다.
'회고' 카테고리의 다른 글
[주간회고] 10월 - 13주차 (0) | 2023.10.24 |
---|---|
[주간회고] 10월 - 12주차 (0) | 2023.10.16 |
[주간회고] 10월 - 11주차 (0) | 2023.10.08 |
[주간회고] 9월 - 10주차 (0) | 2023.09.24 |
[주간회고] 9월 둘째 주 - 9주차 (0) | 2023.09.17 |