첫 주차에는 자바스크립트와 타입스크립트에 대해 학습했다. 학습 과정 중에서 몰랐던 것 위주로 회고를 작성하려고 합니다
JavaScript
호이스팅
호이스팅은 자바스크립트 문법을 선언과 할당으로 구문을 분리하여 선언 부분을 최상위로 끌어올려서 실행하는 특징을 말합니다.
컨텍스트
실행 컨텍스트
실행 컨텍스트는 자바스크립트 코드가 실행되기 위해서 필요한 환경을 제공하는 객체(Object)입니다.
환경 레코드
환경 레코드는 내부적으로 생성 단계와 실행 단계라는 두 가지 단계를 거쳐서 실행됩니다. 생성 단계에서는 현재 컨텍스트의 선언문을 환경 레코드에 기록합니다. 그리고 실행 단계는 생성 단계에서 기록된 환경 레코드를 참조해서 코드를 실행하거나 업데이트 합니다.
자바스크립트는 글로벌 컨텍스트[1]가 실행(Push)되다가 함수를 만나면 함수 실행 컨텍스트가 생성되며(Push)[2] 함수 실행 컨텍스트가 실행이 끝나면(Pop) 다시 글로벌 컨텍스트를 실행하는 구조로 이루어져 있습니다.
let value = 10;
function speak()
{
let value = 20; // 환경 레코드에 기록
console.log(value); // 20 OK!
}
let value = 10;
function speak()
{
// 일시적 사각 지대(TDZ)
// 아래의 value가 환경 레코드에 기록 되었지만 value가 초기화되지 않아 오류 발생
console.log(value); // ReferenceError
let value = 20;
}
위의 예시처럼 자바스크립트가 위에서 아래로 읽어 내려가는 구조임에도 이미 함수내의 키워드는 환경레코드에 기록되고, 호출되는 형식이기에 키워드의 선언 위치에 따라 오류가 발생 할 수가 있습니다.
참고자료
생성자
prototype
자바스크립트의 모든 객체는 자신의 부모 역할을 하는 객체와 연결되어있는데, 이 부모 객체를 프로토타입 객체 또는 프로토타입이라고 합니다.
prototype chain
프로토타입 체인이란 프로토타입의 특징을 이용하여, 상위 프로토타입의 속성과 메소드를 공유받습니다.
JavaScript 기초
Wrapper
JavaScript와 같은 프로그래밍 언어에서, 래퍼는 하나 이상의 다른 기능들을 호출하기 위한 기능입니다. 때로는 순전히 편의상, 때로는 프로세스에서 약간 다른 작업을 하도록 조절하는 기능입니다.
const a = "Hello";
Wrapper로 인해 해당 코드는
const a = new String("Hello");
다른 기능들을 호출하기 위해서 일시적으로 Wrapper됩니다.
Class
정의
Class는 객체를 생성하기 위한 템플릿입니다.
호이스팅
함수 선언과 클래스 선언의 중요한 차이점은 함수의 경우 정의하기 하기 전에 호출할 수 있지만, 클래스는 반드시 정의한 뒤에 사용할 수 있습니다.
const rect1 = new Rectangle(); // ReferenceError
class Rectangle {}
클레스는 호이스팅 될 때, 초기화되지 않습니다.
상속
class Shape {
constructor(color) {
this.color = color;
}
getColor() {
return this.color;
}
}
class Rectangle extends Shape {
constructor(color, width, height) {
super(color); // subclass constructor
this.width = width;
this.height = height;
}
getArea() {
return this.width * this.height;
}
}
const shape = new Rectangle("Blue", 10, 20);
console.log(shape);
console.log(shape.getColor());
Class는 extends를 사용하여 상속을 받을 수 있습니다.
subclass에 constructor가 있다면, "this"를 사용하기 전에 가장 먼저 super()를 호출해야 합니다.
오버 라이딩
Class에서 상속을 받은 클래스는 재정의가 가능합니다.
class Shape {
constructor(color) {
this.color = color;
}
getColor() {
return `도형은 ${this.color}색 입니다.`;
}
}
// 상속 (extends)
class Rectangle extends Shape {
constructor(color, width, height) {
super(color);
this.width = width;
this.height = height;
}
getArea() {
return this.width * this.height;
}
getColor() {
return `사각형은 ${this.color}색 입니다.`;// 재정의(오버라이딩)
}
}
이처럼 함수를 오버라이딩을 하여 상속을 받더라도 다른 동작을 구현 할 수 있습니다.
정적 메서드
Class에서 static을 사용하여 정적 메서드를 생성할 수 있습니다.
정적 메서드는 인스턴스된 객체에서는 호출 할 수 없지만,
클레스 명을 사용하여 호출 할 수 있습니다.
class MathUtils {
static APP_NAME = "Math Utils";
static PI = 3.14;
constructor(number) {
this.number = number;
}
static add(a, b) {
return a + b;
}
}
const mathUtils = new MathUtils(10);
console.log(mathUtils.APP_NAME); // Error : undefined
console.log(mathUtils.add(10, 20)); // Erorr : is not a function
console.log(MathUtils.APP_NAME); // Math Utils
console.log(MathUtils.add(10, 20)); // 30
클로저
클로저는 주변 상태(어휘적 환경)에 대한 참조와 함께 묶인(포함된) 함수의 조합입니다. 즉, 클로저는 내부 함수에서 외부 함수의 범위에 대한 접근을 제공합니다. JavaScript에서 클로저는 함수 생성 시 함수가 생성될 때마다 생성됩니다.
function outer() {
let i = 0;
return function inner() { // 클로저
return i++;
};
}
클로저는 임시메모리에 값이 계속해서 남아있기 때문에, 사용이 종료 됬을시 할당된 값을 초기화 해주는 작업이 필요합니다.
DOM
callback
자바스크립트는 코드를 위에서 아래로 순차적으로 실행합니다. 그러나, 코드가 다른 행위가 일어난 뒤에 실행되는 경우도 있고 순차적으로 실행되지 않을 때도 있습니다.
이러한 문제를 해결하기 위해서 콜백을 사용하여 태스크가 끝나기 전에 함수가 실행되지 않게 보장 할 수 있습니다.
callback Hell
function task1(callback) {
console.log("task1");
callback();
}
function task2(callback) {
setTimeout(() => {
console.log("task2");
callback();
}, 1000);
}
task1(() => task2(() => {});
task1(() => task2(() => task3(() => task4())));
하지만 콜백 사용이 무분별하게 사용될 경우를 Callback Hell 현상이라고 부릅니다. 이러한 형태가 되면 코드의 가독성이 떨어지고, 수정하기가 어려워집니다.
promise
promise는 3가지의 상태를 가집니다.
- pending[대기] - 비동기 처리 로직이 완료되지 않은 상태
- fulfilled[이행] - 비동기 처리가 완료되어 결과 값을 반환해준 상태
- rejected[실패] - 비동기 처리가 실패하거나 오류가 발생한 상태
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, 2000);
});
promise.then(() => {
console.log("resolve 호출시 작동");
});
Promise.then - resolve가 호출될 시 작동하며 비동기 작업을 할 수 있습니다.
Promise.catch - reject가 호출될 시 작동하며 오류를 체크하는데 사용합니다.
Promise.finally - resolve 또는 reject가 호출될 시 작동하며, 공통된 작업이 필요할 경우 사용합니다.
task1()
.then(() => task2())
.catch((err) => console.error(err)) // reject처리
.then(() => task3())
.then(() => task4())
.then(() => console.log("done"));
이러한 기능을 활용하여, 가독성이 높은 비동기 작업을 할 수 있습니다.
Async
Async는 최근에 등장한 비동기 처리 문법으로 기존의 callback 이나 Promise 의 단점을 해소하고자 만들어졌습니다.
async function getApple() {
return "Apple";
}
async function getBanana() {
return "Banan";
}
async function getFruit() {
await getApple().then(() => {});
await getBanana().then(() => {});
}
Promise All
Promise.all() 은 여러 개의 비동기화 함수들을 실행하고자 할 때, 사용할 수 있습니다.
const datas = await Promise.all([getApple(), getBanana()]).then(
(values) => {
console.log(values);
}
);
하지만 Promise all은 한번에 너무 많은 Request 를 서버에 날리게 되면 서버에 과부하를 줄 수 있습니다.
TypeScript
형변환
타입을 검사하여 오류를 잡아내기 위해서 TypeScript를 사용합니다.
타입을 형변환하는 방법은 다음과 같습니다.
const a: string = "Hello"; // 문자열
const b: number = 0; // 숫자
const c: boolean = false; // 참,거짓
const d: null = null; // Null
const e: undefined = undefined; // undefined
const f: object = { name: "john" }; // 오브젝트
const g: symbol = Symbol(); // 심볼
const h: [boolean, string] = [true, "asd"]; // 배열
const i: () => void = function () {}; // 함수
const k: (string | number)[] = []; // 배열
const l: (a: number, b: number) => number = function (a, b) {
return a + b;
}; // 함수 (a[숫자], b[숫자]) 결과[숫자]
타입 키워드
type 키워드를 사용하여 가독성이 높게 작성할 수 있습니다.
type TSnfn = (a: number, b: number) => number;
const l: TSnfn = (a, b) => { return a + b; };
Interface
인터페이스는 객체를 지정하듯이 선언합니다.
인터페이스는 객체만 정의 가능합니다.
인터페이스는 똑같은 키워드를 사용하면 선언 순서에 상관없이 병합됩니다.
유틸리티 타입 (Partial, Omit, Pick)
Partial 모든 속성을 선택적으로 바꾸어줍니다.
Required 모든 속성을 필수적으로 바꾸어줍니다.
Pick 기존의 속성에서 원하는 속성들만 가져와서 사용합니다.
Omit 기존의 속성에서 원하는 속성들을 제외하고 가져와서 사용합니다.
본 후기는 본 후기는 [유데미x스나이퍼팩토리] 프로젝트 캠프 : Next.js 2기 과정(B-log) 리뷰로 작성 되었습니다
'기타' 카테고리의 다른 글
React, TS, Vite 환경에서 프로젝트 세팅 (0) | 2023.12.18 |
---|---|
웹 보안 공격 (0) | 2023.12.16 |
[Vercel] Vercel로 프론트 배포하는법 (0) | 2023.10.27 |