실행컨텍스트란?
실행 컨텍스트란 실행할 코드에게 제공할 정보들을 모아놓은 객체입니다. 함수가 실행되면 실행 컨텍스트가 생성되고, 자바스크립트 엔진에 있는 콜 스택에 쌓이게 됩니다.
콜스택은 후입선출의 구조로 가장 위에 있는 실행컨텍스트부터 실행하면서 전체 코드의 순서를 보장 할 수 있는 것이 실행 컨텍스트입니다.
실행컨텍스트는 언제 생성되나요?
자바스크립트 엔진이 자바 스크립트를 처음 마주할 때 전역 컨텍스트를 생성하고, 콜 스택에 push 합니다. 자바 스크립트를 위에서 아래로 읽어내려가면서 함수 호출을 발견할 때마다, 함수의 실행 컨텍스트를 콜 스택에 push 하게 됩니다. 이 때 함수 실행 컨텍스트는 함수를 선언할 때가 아니라 실행할 때 만들어집니다
실행 컨텍스트 만드는법
실행 컨텍스트를 만들 수 있는 방법으로는 1.전역공간 2.함수 3.eval() 함수가 있습니다.
용어 정리
환경 - 변수, 객체, 함수, this 등 실행할 코드에 제공할 정보들을 모아놓은 객체
프로미스와 콜백 둘 다 자바스크립트에서 비동기 처리를 위해서 사용됩니다. Callback 같은 경우 함수의 처리 순서를 보장하기 위해서 함수를 중첩하게 사용되는 경우가 발생합니다. 이러한 경우 콜백헬이 발생하는 단점과 에러 처리가 힘들다라는 단점이 있습니다.
또한 callback을 사용하면 비동기 로직의 결과값을 처리하기 위해서 callback안에서만 처리를 해야하고, 콜백 밖에서는 비동기에서 온 값을 알 수가 없습니다. 이를 보완하기 위해 promise를 나왔습니다. promise를 사용하면 비동기에에서 온 값이 promise 객체에 저장되기 때문에 .then, .catch를 이용해 쉽게 사용할 수 있습니다. 성공적으로 작업이 완료되면, resolve함수를 호출하고 오류가 발생하면 reject를 호출합니다. 이후 resolve 함수는 then을 통해 받을 수 있고, 실패하면 catch를 통해 받을 수 있습니다.
용어 정리
비동기 - 특정 코드의 실행이 완료될 때까지 기다리지 않고 다음 코드를 먼저 수행하는 것을 말합니다.
주요 키워드 - 비동기
꼬리질문
프로미스의 상태에 대해 설명해보세요
pending, fulfilled, rejected 3가지 상태가 있습니다. 하나 하나 설명하자면
pending: 이행되거나 거부되지 않은 초기상태를 말한다.
fulfilled: 연산이나 작업이 성공적으로 완료된 상태를 말한다.
rejected: 연산이나 작업이 실패한 상태를 말한다.
프로미스는 위 3가지 중 하나의 상태를 가지며,
프로미스란
Promise란 비동기 작업이 종료되고 난 후, 결과 값이나 오류를 처리할 수 있도록 연결하는 객체다. 한 마디로 JavaScript에서 비동기 함수 로직을 처리한 이후의 결과를 얻기 위한 함수이다.
콜백 함수란
Callback 함수란 다른 함수의 매개변수(parameter)로 함수를 전달하고, 어떤 이벤트가 발생한 후 매개변수로 전달한 함수가 다시 호출되는 것을 말한다
캡틴 판교의 Promise 정리글
https://joshua1988.github.io/web-development/javascript/promise-for-beginners/
async는 function 앞에 위치하며 async 함수는 항상 프라미스를 반환합니다.
await를 만나면 프라미스의 작업이 완료될 때 까지 기다린 후 결과를 반환합니다.
출처 : https://ko.javascript.info/async-await
var - 재선언 재할당 가능
1.선언 및 초기화단계 동시 진행
2.할당단계
let - 재선언 불가 재할당 가능(Mutable)
1.선언 단계
2.초기화단계
3.할당단계
const - 재선언 재할당 불가능(Immutable)
1.선언 및 초기화 및 할당 단계
const = 변수에 저장된 값을 변경하지 않겠다는 의미 X
변수가 처음 할당받은 메모리 주소를 변경하지 않겠다는 의미 O
참조형 데이터 (예: object, array, function)는 변수에 값이 아닌 메모리 주소가 저장된다. 실제 값은 힙(Heap)이라는 메모리 공간에 따로 저장되며, 변수가 이 주소를 참조하게 됩니다.
const num = 42;
num = 50; // 오류 발생! (num에 다른 값을 할당할 수 없음)
const obj = { name: "kk", age: 1 };
obj = { name: "kk2", age: 2 }; // 오류 발생! (obj에 다른 객체를 할당할 수 없음)
obj.name = "kk2"; // 정상 동작
자바스크립트 생성 단계
자바스크립트에서는 총 3단계에 걸쳐 변수를 생성합니다.
선언 단계(Declaration phase)
변수 객체(Variable Object)를 생성하고 변수를 등록한다.
스코프는 해당 변수 객체를 참조한다.
초기화 단계(Initialization phase)
변수 객체(Variable Object)에 등록된 변수를 메모리에 할당한다.
변수는 undefined로 초기화된다.
할당 단계(Assignment phase)
undefined로 초기화된 변수에 실제값을 할당한다.
용어 정리
var는 함수 스코프, let과 const는 블록 스코프
함수스코프 - 함수에서 선언된 것은 벗어날 수 없음 나머지 스코프는 벗어날 수 있음
블록스코프 - 스코프 내에 선언된 것은 스코프를 벗어날 수 없음
Mutable - 생성된 이후에 상태가 변경될 수 있는 객체
Immutable - 생성된 이후에 상태가 변경되지 않는 객체
호이스팅이란 스코프 내부 어디서든 변수 선언은 최상위에 선언된 것 처럼 행동하는 것을 말합니다. 예를 들어 1번 라인에서 함수를 실행 코드가 있고, 그 함수에 대한 선언이 2번 라인에 있다 하더라도 함수는 잘 실행이 됩니다. 또한 호이스팅은 선언에만 일어납니다. 그렇기 때문에 값을 할당하더라도 할당된 값은 호이스팅이 일어나지 않습니다. 호이스팅의 대상으로는 변수선언과 함수선언이 있습니다. 그리고 let과 const는 호이스팅이 일어나지만 Reference Error가 발생하게됩니다. 왜냐하면 var과 달리 let과 const에는 TDZ가 있기 때문입니다. TDZ에 접근할 경우 Reference Error가 발생하게됩니다. var는 TDZ가 존재하지 않고 선언과 동시에 undefined로 초기화됩니다. 함수 선언문 또한 호이스팅이 일어납니다.
선언 - var a = "hi"
할당 - a = "hi"
라이프사이클 - 컴퓨터 시스템의 모든 자원은 라이프 사이클 즉, 생애 주기를 가집니다.생애주기란 생성되고 사용되며 소멸되는 메커니즘을 말합니다. 컴퓨터 시스템의 자원은 유한하기 때문에 자원을 효과적으로 사용하기 위해 고안된 방식이 라이프 사이클입니다.
TDZ - 일시적인 사각지대로, 변수 사용을 허용하지 않는 공간
함수 선언문 - 함수를 선언함
함수 표현식 - 변수에 함수를 할당함. 할당은 호이스팅 되지 않음
함수 선언문은 호이스팅이 되고 함수 표현식은 호이스팅이 되지 않는다.
클로저는 함수와 그 함수의 렉시컬 환경의 조합입니다. 여기서 렉시컬 환경이란 자바스크립트에서 실행할 변수와 함수를 프로퍼티로 갖는 객체입니다. 내부 함수가 실행되면 내부 렉시컬 환경에서 변수를 찾습니다. 만약 내부 렉시컬 환경에서 변수를 찾지 못한다면 외부 렉시컬 환경으로 올라가 변수를 찾게 됩니다. 즉 클로저란 함수가 생성될 당시의 외부 변수를 기억하고 그 변수에 계속해서 접근이 가능한 기능입니다.
주요 키워드 - 렉시컬 환경
프로퍼티 : 프로퍼티는 "key(키)" : "value(값)" 의 형식으로 객체 안의 쉼표로 구분되어 할당된다. 프로퍼티의 값이 함수라면 그것은 메소드
javascript에서 this는 자기참조 객체이며 함수가 어떻게 호출되었는지에 따라 this에 값이 달라지게 됩니다.
전역 공간 - 전역객체를(window)와 바인딩됩니다.
함수 호출 - 기본적으로 전역 객체(window)와 바인딩됩니다.
메소드 호출 - 메서드 호출 객체를 바인딩합니다.
생성자 함수 - 생성할 인스턴스와 바인딩됩니다.
화살표 함수 - 선언될 시점에서의 상위 스코프가 this로 바인딩됩니다
call - 함수를 실행하고 함수의 첫 번째 인자에 this를 바인딩한다.
apply - 인자를 배열의 형태로 전달
bind - 함수를 실행하지 않고, 새로운 함수를 반환합니다.
바인딩(binding)
메모리에 값을 할당하는 것
특정한 객체와 this를 묶어놓은 것은 this 바인딩이라고 칭한다.
생성자
자바스크립트의 생성자 함수는 말 그대로 객체를 생성하는 역할을 한다
주요 키워드 - 자기참조 객체
이벤트 버블링이란 선택한 요소의 핸들러가 동작하면 부모 요소의 핸들러도 동작하는 것을 말합니다. 이렇게 가장 최상단인 document 객체를 만날 때 까지 반복합니다.
이벤트 캡처링이란 버블링과는 반대로 최상위 태그에서 해당 태그를 찾아 내려가는 것 입니다.
이벤트 버블링을 막는 방법은 event.stopPropagation() 명령을 사용하여 막을 수 있습니다.
주요 키워드 - 최상단
용어정리
요소 - <></> p태그,div태그의 처음부터 끝을 요소라고 함
요소의 공통 조상에 이벤트 핸들러를 단 하나만 할당해도 여러 요소를 한꺼번에 다룰 수 있습니다. (코드가 간결해지고 html 구조가 유연해진다.)
이벤트 추가하기 - addEventListener(type, eventListener)
이벤트 제거하기 - removeEventListener(type, eventListener)
type = click, keydown 등
eventListener = 실행할 함수
원시 자료형
string, number, bigint, boolean, undefined, symbol, null
원시 자료형 예시
let a = 1;
let b = 1;
console.log(a === b); //true
참조 자료형
배열, 객체, 함수가 있다.
메모리의 같은 공간을 참조할 경우에는 같은 데이터
다른 메모리의 공간을 참조할 경우에는 다른 데이터
const a = [1,2,3];
const b = a;
console.log(a === b); //true
const a = [1,2,3];
const b = [1,2,3];
console.log(a === b); //false
const a = [1,2,3];
const b = a;
b.push(4);
console.log(a); //[1,2,3,4]
같은 배열 공간을 참조하고 있기 때문에 데이터를 추가할 경우 같은 참조 공간이 변경된 것이다.
얕은 비교 - 기본 타입 데이터의 경우 값이 동일한지만 비교하고, 객체의 경우 참조만 비교한다.
const obj1 = { a: 1, b: 2 };
const obj2 = { a: 1, b: 2 };
console.log(obj1 === obj2); // false
깊은 비교
얕은 비교와 달리 깊은 비교는 객체의 경우에도 값으로 비교한다. 깊은 비교 방법은 아래와 같다.
1️⃣ Object depth가 깊지 않은 경우 : JSON.stringify() 사용
2️⃣ Object depth가 깊은 경우 : lodash 라이브러리의 isEqual() 사용
const obj1 = { a: 1, b: 2 };
const obj2 = { a: 1, b: 2 };
console.log(JSON.stringify(obj1) === JSON.stringify(obj2)); // true
얕은 복사는 객체의 주소 값을 복사하고, 깊은 복사는 객체의 실제 값을 복사합니다.
깊은 복사
const a = 'a';
let b = 'b';
b = 'c';
console.log(a); // 'a';
console.log(b); // 'c';
// 기존 값에 영향을 끼치지 않는다.
원시자료형을 복사할 때 그 값은 또 다른 메모리 공간에 할당하기 때문에, 복사를 하고 값을 수정해도 기존 원시값을 저장한 변수에는 영향을 끼치지 않습니다.
얕은복사
const a = {
one: 1,
two: 2,
};
let b = a;
b.one = 3;
console.log(a); // { one: 3, two: 2 } 출력
console.log(b); // { one: 3, two: 2 } 출력
// 기존 값에 영향을 끼친다.
참조 자료형을 복사할 때는 변수가 객체의 참조를 가리키고 있기 때문에 복사된 변수 또한 객체가 저장된 메모리 공간의 참조를 가리키고 있습니다. 그래서 복사를 하고 객체를 수정하면 두 변수는 똑같은 참조를 가리키고 있기 때문에 기존 객체를 저장한 변수에 영향을 끼칩니다.
reference : https://bbangson.tistory.com/78
얕은 복사 방법
consr arr = [1,2,3];
const myArr = arr.slice();
얕은 복사 방법의 대표적인 예. start와 end를 설정하지 않는다면, 기존 배열을 전체 얕은 복사한다. 또한 스프레드연산자[...] 을 사용하면 된다
깊은복사 방법
깊은 복사된 객체는 객체 안에 객체가 있을 경우에도 원본과의 참조가 완전히 끊어진 객체를 말합니다.
방법 1 : lodash 라이브러리의 isEqual() 사용. 하지만 라이브러리 이기 때문에 코딩테스트에서 사용할 수 없음
방법 2 : JSON.stringify() 사용. 단점 : 느리고 객체가 function일 경우 undefinded로 처리한다는 단점
== -> 느슨한 동등 비교 연산자(loose equality comparison)
두 변수가 타입이 달라도 같은 값을 가지면, true를 반환한다.
두 변수를 비교할 때 타입이 서로 다르면 타입 변환을 수행한다.
=== -> 엄격한 동등 비교 연산자(strict equality comparison)
두 변수의 타입이 같고, 같은 값을 가질 때, true를 반환한다.
비교할 때 타입 변환이 일어나지 않는다.
테스트 코드는 기능이나 동작이 예상대로 동작하는지 확인하기 위한 코드입니다 버그를 미리 발견할 수 있으며, 코드를 변경하거나 리팩토링할 때마다 테스트 코드를 실행해보면서 예상치 못한 버그를 발견할 수 있다는 장점이 있습니다.
Jest - Facebook에서 만든 자바스크립트 테스트 프레임워크로 간단하고 사용하기 쉽습니다.
Enzyme - React 컴포넌트를 테스트하는 데 사용되는 라이브러리입니다.
특히 Shallow rendering을 통해 컴포넌트를 가상으로 렌더링하여 테스트하는 것이 특징입니다.
TDD - 테스트 코드를 먼저 작성하고 그 테스트를 통과시키기 위한 최소한의 코드만 작성한 후 리펙토링 수행
저는 TDD 방법론을 이용한 Jest를 이용하여 테스트 코드를 작성해보았습니다.
Throttling과 Debouncing은 둘 다 이벤트를 제어하는 기술로 반응성을 향상시키고 서버의 부하를 줄여준다.
Throttling - 이벤트가 발생하는 속도를 제한 | 이벤트가 지속적으로 발생하는 경우 사용
ex) 사용자가 스크롤하면, 스크롤 이벤트가 매우 빠르게 발생할 수 있습니다. 이 경우 Throttling을 사용하면 일정 시간마다 이벤트를 처리하도록 지연시킵니다. 이렇게 함으로써, 서버에서 처리하는 요청 수를 줄이고, 응답 시간을 향상시킬 수 있습니다.
Debouncing은 이벤트가 발생하면 일정 시간이 지난 후에 해당 이벤트를 처리하는 것 | 이벤트가 일시적으로 발생하는 경우 사용
ex) 사용자가 검색어를 입력하면, 검색어 이벤트가 빈번하게 발생할 수 있습니다. 이 경우 Debouncing을 사용하면 사용자가 입력을 완료하기 전에 일정 시간이 지나면 검색어를 처리합니다. 이렇게 함으로써, 불필요한 검색 요청을 줄이고, 응답 시간을 향상시킬 수 있다.
TypeScript
장점
타입을 지정할 수 있어 잘못된 변수가 들어오면 vsc에서 에러를 미리 알려준다.
타입이 지정되어있어 그 타입에 맞는 API를 자동완성으로 보여준다.
정적 타입 체크로 인한 높은 코드 안정성과 가독성.
단점
타입 선언이 필요하여 JavaScript에 비해 코드량이 많음
Javascript
장점
학습이 쉽고, 문법이 간결하며, 코드 양이 적어 작성 및 유지보수가 용이함
동적 타입 체크로 인한 유연성과 자유도가 높음
단점
대규모 프로젝트에서 코드 재사용성 및 유지보수가 어려울 수 있음
가장 큰 차이점은 타입의 확장 가능 여부
타입 - 나중에 쉽게 참조 할 수 있도록 이름을 부여하는 것. 타입에 마우스를 올리면 상세 정보가 나온다
인터페이스 - 새로운 타입 값을 선언하여 ctrl + 클릭을 하면 그 인터페이스로 이동한다. 또한 확장이 가능하다
제네릭이란 타입을 마치 함수의 파라미터처럼 사용하는 것을 의미한다
// 제네릭 문법이 적용된 상태
function getText<T>(text: T): T {
return text;
}
// 제네릭 함수를 사용한다
getText<string>('hi');
// 결과
function getText<string>(text: string): string {
return text;
}
이넘은 특정 값들의 집합을 의미하는 자료형이다.
숫자형 이넘
enum Shoes {
Nike,
Adidas
}
console.log(Shoes.Nike) // 0
console.log(Shoes.Adidas) // 1
이넘을 선언할 때 별도의 값을 넣지 않으면 숫자형 이넘이 된다.
숫자형 이넘은 값이 자동으로 증가한다
문자형 이넘
enum Shoes {
Nike = '나이키',
Adidas = '아디다스'
}
console.log(Shoes.Nike) // 나이키
console.log(Shoes.Adidas) // 아디다스
이넘의 활용
함수에 매개변수 타입을 그냥 string으로 했다고 하자. 그렇다면 "Yes" 던 "y" 던 "예스" 던 들어갈 수 있다. 이것을 방지하기 위해 이넘을 사용해서 특정한 값만 전달인자로 받을 수 있게 하는 것이 이넘이다.
enum Answer {
Yes = 'Y',
No = 'N'
}
const askQuestion = (answer: Answer) => { // 타입으로 이넘을 넣는다
if(answer === Answer.Yes) console.log("정답");
}
askQuestion(Answer.Yes); // 올바름
askQuestion("Yes") // 오류
그냥 오버라이딩과 같다고 보면 될 것 같다
요소는 content padding border으로 구성되어 있습니다. padding은 content와 border 사이의 공간이고 margin은 border 밖의 공간입니다.
static - 기본값 HTML 문서 상에서 원래 있어야 하는 위치에 배치 top bottom left right 무시됨
relative - top bottom left right 속성을 이용해 원래 위치보다 상하좌우 떨어지게 할 수 있다.
abosolute - 배치 기준을 자신이 아닌 상위 요소를 기준으로 잡는다. 요소의 diplay를 abosolute로 설정하면 그 부모를 relative로 지정해 주는 것이 관례
fixed - 요소를 항상 고정된 위치에 배치
sticky - 브라우저를 스크롤 할때 상단에 붙어버림