JavaScript
1. import & export
export: 다른 파일에서 접근 가능하도록 변수, 함수 또는 클래스를 표시합니다.import: 다른 파일의 기능을 포함시킵니다.
2. default export
default export는 파일당 한 번만 사용할 수 있습니다.
3. var, let, const
var: 변수를 선언하는 키워드입니다. 함수 스코프를 가지며, 중복 선언이 가능합니다.let: 블록 스코프를 가지며, 중복 선언이 불가능합니다.const: 블록 스코프를 가지며, 중복 선언이 불가능하며, 재할당이 불가능합니다.
4. 연산자
- 수학 연산자:
+,-,*,/를 포함하여 기본적인 수학 연산을 수행합니다. - 문자열 연산:
+연산자는 문자열을 결합하는 데도 사용됩니다.
5. 비교 연산자
==: 값이 같은지 비교합니다.===: 값과 타입이 같은지 비교합니다.
6. 조건문
if: 조건이 참이면 코드 블록을 실행합니다.else if: 이전 조건이 거짓이고 현재 조건이 참이면 코드 블록을 실행합니다.else: 이전 조건이 거짓이면 코드
switch: 여러 조건을 비교할 때 사용합니다.case: switch 문에서 비교할 값입니다.break: switch 문에서 case 문을 종료합니다.default: switch 문에서 case에 해당하는 값이 없을 때 실행합니다.
7. 함수
- 함수: 코드 블록을 정의하고 이름을 지정하여 재사용 가능한 코드 조각을 만듭니다.
- 매개변수: 함수에 전달되는 값을 저장하는 변수입니다.
- 반환 값: 함수가 실행되고 값을 반환하는 경우 반환되는 값입니다.
- 화살표 함수: 함수를 간결하게 작성할 수 있는 방법입니다.
- 기명 함수: 함수에 이름을 지정하는 방법입니다.
- 익명 함수: 함수에 이름을 지정하지 않는 방법입니다.
- 콜백 함수: 다른 함수의 인수로 전달되는 함수입니다.
- 중첩 함수: 함수 내부에 정의된 함수입니다.
- 재귀 함수: 함수가 자신을 호출하는 함수입니다.
- 생성자 함수: 객체를 생성하는 함수입니다.
8. 클래스
- 클래스: 객체를 생성하기 위한 설계도입니다.
- 생성자: 클래스로부터 객체를 생성하는 함수입니다.
- 상속: 클래스가 다른 클래스의 속성과 메서드를 상속받는 것입니다.
- 프로토타입: 객체의 속성과 메서드를 상속받는 것입니다.
- 인스턴스: 클래스로부터 생성된 객체입니다.
- 메서드: 객체의 동작을 나타내는 함수입니다.
- 속성: 객체의 상태를 나타내는 변수입니다.
this: 현재 객체를 참조하는 키워드입니다.super: 부모 클래스를 참조하는 키워드입니다.static: 정적 메서드를 정의하는 키워드입니다.getter: 속성 값을 가져오는 메서드입니다.setter: 속성 값을 설정하는 메서드입니다.extends: 클래스가 다른 클래스를 상속받는 키워드입니다.
9. 객체
- 객체: 속성과 메서드를 포함하는 데이터 구조입니다.
- 속성: 객체의 상태를 나타내는 변수입니다.
- 메서드: 객체의 동작을 나타내는 함수입니다.
- 프로퍼티: 객체의 속성과 메서드를 포함하는 데이터입니다.
- 프로토타입: 객체의 속성과 메서드를 상속받는 것입니다.
- 인스턴스: 클래스로부터 생성된 객체입니다.
this: 현재 객체를 참조하는 키워드입니다.new: 객체를 생성하는 키워드입니다.Object: 객체를 생성하는 내장 함수입니다.Object.keys(): 객체의 속성 이름을 배열로 반환합니다.Object.values(): 객체의 속성 값을 배열로 반환합니다.Object.entries(): 객체의 속성을 [키, 값] 쌍으로 배열로 반환합니다.Object.assign(): 객체를 병합합니다.Object.create(): 객체를 생성합니다.Object.defineProperty(): 객체의 속성을 정의합니다.Object.getOwnPropertyDescriptor(): 객체의 속성을 반환합니다.Object.freeze(): 객체를 동결합니다.Object.seal(): 객체를 밀봉합니다.Object.preventExtensions(): 객체에 새로운 속성을 추가하지 못하게 합니다.Object.is(): 두 값이 같은지 비교합니다.Object.setPrototypeOf(): 객체의 프로토타입을 설정합니다.Object.getPrototypeOf(): 객체의 프로토타입을 반환합니다.getter: 속성 값을 가져오는 메서드입니다.setter: 속성 값을 설정하는 메서드입니다.
10. 배열
- 배열: 여러 값을 저장하는 데이터 구조입니다.
- 인덱스: 배열 요소의 위치를 나타내는 숫자입니다.
- 요소: 배열에 저장된 값입니다.
- 길이: 배열의 요소 수입니다.
push(): 배열 끝에 요소를 추가합니다.pop(): 배열 끝의 요소를 제거합니다.shift(): 배열 앞의 요소를 제거합니다.unshift(): 배열 앞에 요소를 추가합니다.splice(): 배열 요소를 추가, 제거 또는 교체합니다.slice(): 배열의 일부를 복사합니다.concat(): 배열을 병합합니다.reverse(): 배열을 역순으로 정렬합니다.sort(): 배열을 정렬합니다.indexOf(): 배열에서 요소의 인덱스를 검색합니다.lastIndexOf(): 배열에서 요소의 마지막 인덱스를 검색합니다.includes(): 배열에 요소가 포함되어 있는지 확인합니다.find(): 배열에서 조건을 만족하는 첫 번째 요소를 반환합니다.findIndex(): 배열에서 조건을 만족하는 첫 번째 요소의 인덱스를 반환합니다.filter(): 배열에서 조건을 만족하는 요소를 반환합니다.map(): 배열의 모든 요소에 함수를 적용한 결과를 반환합니다.reduce(): 배열의 요소를 하나의 값으로 줄입니다.forEach(): 배열의 모든 요소에 함수를 적용합니다.every(): 배열의 모든 요소가 조건을 만족하는지 확인합니다.some(): 배열의 요소 중 하나라도 조건을 만족하는지 확인합니다.join(): 배열 요소를 문자열로 변환합니다.toString(): 배열을 문자열로 변환합니다.isArray(): 배열인지 확인합니다.of(): 배열을 생성합니다.from(): 배열을 복사합니다.fill(): 배열 요소를 채웁니다.copyWithin(): 배열 요소를 복사합니다.flat(): 중첩 배열을 평탄화합니다.flatMap(): 배열을 매핑하고 평탄화합니다.entries(): 배열의 [인덱스, 요소] 쌍을 반환합니다.keys(): 배열의 인덱스를 반환합니다.values(): 배열의 요소를 반환합니다.
11. destructuring
- 구조 분해 할당: 배열이나 객체에서 값을 추출하여 변수에 할당하는 것입니다.
- 배열 구조 분해: 배열에서 값을 추출하여 변수에 할당하는 것입니다.
- 객체 구조 분해: 객체에서 값을 추출하여 변수에 할당하는 것입니다.
- 기본값: 구조 분해 할당 시 기본값을 설정하는 것입니다.
- 중첩 구조 분해: 중첩된 배열이나 객체에서 값을 추출하는 것입니다.
- 나머지 요소: 나머지 요소를 배열로 할당하는 것입니다.
- 전개 구문: 배열이나 객체를 확장하는 것입니다.
12. 함수 매개변수 목록에서 디스트럭처링
- 함수 매개변수 목록에서 디스트럭처링: 함수 매개변수 목록에서 객체나 배열을 구조 분해하는 것입니다.
- 기본값: 함수 매개변수 목록에서 기본값을 설정하는 것입니다.
- 나머지 매개변수: 함수 매개변수 목록에서 나머지 매개변수를 배열로 할당하는 것입니다.
- 전개 구문: 함수 매개변수 목록에서 배열을 확장하는 것입니다.
13. 반복문
- 반복문: 코드 블록을 반복 실행하는 제어 구조입니다.
for: 조건을 만족할 때까지 코드 블록을 반복 실행합니다.for...in: 객체의 열거 가능한 속성을 반복합니다.for...of: 반복 가능한 객체의 요소를 반복합니다.while: 조건을 만족할 때까지 코드 블록을 반복 실행합니다.do...while: 코드 블록을 실행한 후 조건을 만족할 때까지 반복 실행합니다.break: 반복문을 종료합니다.continue: 반복문의 나머지 코드를 건너뜁니다.
14. 참조형 값 및 원시값
JavaScript에서 데이터는 크게 두 가지 유형으로 분류됩니다: 원시값(Primitive values)과 참조형 값(Reference values).
이 두 유형의 차이는 데이터의 저장, 접근 방식, 그리고 복사 시의 동작에 영향을 미칩니다.
원시값 (Primitive Values):
- 원시값은 불변의 가장 기본적인 데이터 유형입니다. 원시 데이터 유형에는 다음과 같은 것들이 있습니다:
- Number: 숫자를 나타내며, 정수와 실수를 포함합니다.
- String: 문자열을 나타내며, 텍스트 데이터를 표현합니다.
- Boolean: 불린 값(true 또는 false)을 나타냅니다.
- undefined: 변수가 값 없이 선언되었을 때 사용되는 값입니다.
- null: 의도적으로 변수에 값이 없음을 나타내는 데 사용됩니다.
- Symbol (ES6 이후): 고유하고 변경 불가능한 데이터 타입으로 주로 객체 속성의 식별자로 사용됩니다.
- BigInt (ES2020 이후): 매우 큰 정수를 나타내기 위한 데이터 타입입니다.
- 원시값의 특징은 다음과 같습니다:
- 불변성: 원시값 자체를 변경할 수 없습니다. 값을 변경하는 것처럼 보이는 연산을 수행하면, 새로운 원시값을 생성하고 변수는 새로운 값으로 업데이트됩니다.
- 값에 의한 복사: 변수에 원시값을 할당하고 다른 변수에 이 값을 할당하면, 실제 값이 복사됩니다. 각 변수는 독립적인 값을 가지게 됩니다.
- 원시값은 불변의 가장 기본적인 데이터 유형입니다. 원시 데이터 유형에는 다음과 같은 것들이 있습니다:
참조형 값 (Reference Values)
- 참조형 값은 객체, 배열, 함수 등과 같은 복잡한 데이터 구조를 포함합니다. 참조형의 특징은 다음과 같습니다:
- 변경 가능성: 참조형 값은 변경 가능합니다. 객체의 속성을 수정하거나 배열에 요소를 추가하는 등의 작업이 가능합니다.
- 참조에 의한 복사: 변수에 객체를 할당하고 다른 변수에 이 객체를 할당하면, 원본 객체의 참조(메모리 주소)가 복사됩니다. 따라서 두 변수는 동일한 객체를 가리키게 되어, 한 변수를 통해 객체를 변경하면 다른 변수를 통해 접근한 객체도 그 변경을 반영합니다.
- 참조형 값은 객체, 배열, 함수 등과 같은 복잡한 데이터 구조를 포함합니다. 참조형의 특징은 다음과 같습니다:
----------------------
15. 호출 스택 알아보기
자바스크립트의 실행 원리: 호출 스택과 비동기 처리
자바스크립트에서 코드가 어떻게 실행되는지 이해하려면 호출 스택(Call Stack)과 비동기 처리(Asynchronous Processing)를 잘 알아야 합니다.
이 두 가지 개념을 이해하면, 자바스크립트 코드가 어떤 순서로 실행되고, 비동기 작업이 어떻게 처리되는지 명확하게 알 수 있습니다.
호출 스택(Call Stack)
호출 스택은 자바스크립트가 함수 호출을 관리하는 방식입니다.
함수를 호출할 때마다 호출 스택에 쌓이고, 함수 실행이 끝나면 스택에서 제거됩니다.
이 과정을 통해 자바스크립트는 함수 실행 순서를 관리합니다.
function first() {
second();
console.log('첫번째');
}
function second() {
third();
console.log('두번째');
}
function third() {
console.log('세번째');
}
first();비동기 처리와 이벤트 루프(Event Loop)
비동기 처리는 자바스크립트가 시간 소요가 많은 작업을 효율적으로 처리하는 방식입니다.
이벤트 루프(Event Loop)는 비동기 작업이 완료되었을 때 호출 스택이 비어있으면 콜백 함수를 실행하는 역할을 합니다.
console.log('시작');
setTimeout(function run() {
console.log('3초 후 실행');
}, 3000);
console.log('끝');16. 이벤트 루프 알아보기
자바스크립트의 실행 원리: 호출 스택, 백그라운드, 태스크 큐, 이벤트 루프
자바스크립트가 어떻게 코드를 실행하는지 이해하려면 호출 스택, 백그라운드, 태스크 큐, 이벤트 루프의 개념을 알아야 합니다.
이 개념들은 자바스크립트의 동작 원리를 이해하는 데 필수적입니다.
호출 스택 (Call Stack)
호출 스택은 자바스크립트 함수 호출을 관리하는 구조입니다.
함수가 호출되면 호출 스택에 쌓이고, 함수 실행이 끝나면 스택에서 제거됩니다.
백그라운드 (Background)
백그라운드는 비동기 작업을 처리하는 곳입니다.
비동기 함수가 호출되면, 백그라운드에서 처리됩니다.
태스크 큐 (Task Queue)
태스크 큐는 백그라운드에서 완료된 비동기 작업의 콜백 함수가 대기하는 곳입니다.
태스크 큐에 있는 함수는 호출 스택이 비어있을 때 실행됩니다.
이벤트 루프 (Event Loop)
이벤트 루프는 호출 스택이 비어 있을 때 태스크 큐에서 대기 중인 콜백 함수를 호출 스택으로 가져오는 역할을 합니다.
console.log('시작');
setTimeout(function run() {
console.log('3초 후 실행');
}, 3000);
console.log('끝');console.log('시작');
setTimeout(function() {
console.log('첫 번째 타이머');
}, 0);
Promise.resolve().then(function() {
console.log('첫 번째 프로미스');
});
console.log('끝');17. var, const, let
자바스크립트의 변수 선언 방식: var, let, const
자바스크립트에는 변수를 선언하는 세 가지 방법이 있습니다: var, let, const.
이 세 가지 방식의 차이점과 사용법에 대해 알아보겠습니다.
var
var는 자바스크립트에서 변수를 선언하는 가장 오래된 방법입니다.
하지만 최근에는 거의 사용되지 않습니다.
그 이유는 var가 가지고 있는 몇 가지 단점 때문입니다.
var의 특성
- 함수 스코프(
Function Scope):var로 선언한 변수는 함수 스코프를 따릅니다. 즉, 변수가 함수 내에서 선언되면 그 함수 내 어디에서든 접근할 수 있습니다. - 호이스팅(
Hoisting):var로 선언된 변수는 선언하기 전에 사용할 수 있습니다. 이는 자바스크립트가 변수 선언을 코드의 최상위로 끌어올리기 때문입니다.
function example() {
console.log(x); // undefined
var x = 10;
console.log(x); // 10
}
example();let
let은 블록 스코프(Block Scope)를 따르는 변수 선언 방법입니다.
이는 var의 단점을 보완하기 위해 ES6(ECMAScript 2015)에서 도입되었습니다.
let의 특성
- 블록 스코프(
Block Scope):let으로 선언한 변수는 블록 내에서만 유효합니다. 블록은 중괄호{}로 구분됩니다. - 호이스팅 없음:
let은 선언 전에 사용할 수 없습니다.
function example() {
console.log(x); // ReferenceError
let x = 10;
console.log(x); // 10
}
example();const
const는 상수(Constant)를 선언하는 방법입니다.
한 번 값을 할당하면 재할당할 수 없습니다.
const의 특성
- 블록 스코프(
Block Scope):const는let과 마찬가지로 블록 스코프를 따릅니다. - 재할당 불가:
const로 선언된 변수는 값을 한 번만 할당할 수 있으며, 이후에는 값을 변경할 수 없습니다.
const x = 10;
x = 20; // TypeError: Assignment to constant variable.const와 객체
const로 객체를 선언할 때는 객체 자체는 재할당할 수 없지만, 객체의 프로퍼티는 변경할 수 있습니다.
const obj = { name: 'Alice' };
obj.name = 'Bob'; // 가능
console.log(obj.name); // 'Bob'
obj = { name: 'Charlie' }; // TypeError: Assignment to constant variable.var, let, const의 비교
| 특징 | var | let | const |
|---|---|---|---|
| 스코프 | 함수 스코프 | 블록 스코프 | 블록 스코프 |
| 호이스팅 | 있음 | 없음 | 없음 |
| 재할당 | 가능 | 가능 | 불가 |
| 선언 전 사용 | 가능 | 불가 | 불가 |
결론
let: 변수를 선언할 때 기본적으로 사용합니다. 블록 스코프를 따르므로 코드의 예측 가능성을 높여줍니다.const: 값을 재할당할 필요가 없을 때 사용합니다. 객체나 배열을 선언할 때 유용합니다.var: 과거의 유산으로, 새로운 코드에서는 사용하지 않는 것이 좋습니다.
18. 템플릿 문자열, 객체 리터럴
자바스크립트 최신 문법: 템플릿 리터럴과 객체 리터럴
템플릿 리터럴 (Template Literals)
템플릿 리터럴은 문자열을 더 쉽게 조작할 수 있도록 도와주는 ES6(ECMAScript 2015) 문법입니다.
백틱(`) 기호를 사용하여 문자열을 작성하며, 변수나 표현식을 ${}로 감쌀 수 있습니다.
예시
옛날 방식으로 문자열을 조합할 때는 다음과 같이 했습니다:
let name = '홍길동';
let age = 25;
let result = '이름은 ' + name + '이고 나이는 ' + age + '살입니다.';
console.log(result); // 이름은 홍길동이고 나이는 25살입니다.이 방식은 가독성이 떨어지고, 띄어쓰기를 실수로 빼먹기 쉽습니다.
템플릿 리터럴을 사용하면 다음과 같이 간단하게 작성할 수 있습니다:
let name = '홍길동';
let age = 25;
let result = `이름은 ${name}이고 나이는 ${age}살입니다.`;
console.log(result); // 이름은 홍길동이고 나이는 25살입니다.템플릿 리터럴을 사용하면 문자열 내에서 변수와 표현식을 쉽게 포함시킬 수 있으며, 가독성도 높아집니다.
태그드 템플릿 리터럴 (Tagged Template Literals)
템플릿 리터럴에 태그를 붙여서 함수를 호출하는 방식입니다.
함수 이름 뒤에 백틱(`)을 사용하여 템플릿 리터럴을 호출합니다.
예시
function tag(strings, ...values) {
console.log(strings); // ['이름은 ', '이고 나이는 ', '살입니다.', raw: Array(3)]
console.log(values); // ['홍길동', 25]
return '출력 결과';
}
let name = '홍길동';
let age = 25;
let result = tag`이름은 ${name}이고 나이는 ${age}살입니다.`;
console.log(result); // 출력 결과tag 함수는 템플릿 리터럴의 문자열 부분과 변수 값을 분리하여 전달받습니다.
객체 리터럴 (Object Literals)
객체 리터럴도 ES6에서 편의성이 많이 개선되었습니다.
예시
옛날 방식:
let name = '홍길동';
let age = 25;
let person = {
name: name,
age: age
};
console.log(person); // { name: '홍길동', age: 25 }축약형:
let name = '홍길동';
let age = 25;
let person = { name, age };
console.log(person); // { name: '홍길동', age: 25 }동적 속성 이름 (Computed Property Names)
객체의 속성명을 동적으로 지정할 수 있습니다.
예시
옛날 방식:
let prop = 'name';
let person = {};
person[prop] = '홍길동';
console.log(person); // { name: '홍길동' }동적 속성 이름 사용:
let prop = 'name';
let person = {
[prop]: '홍길동'
};
console.log(person); // { name: '홍길동' }메서드 축약 (Method Shorthand)
객체 내에서 함수를 정의할 때 function 키워드를 생략할 수 있습니다.
예시
옛날 방식:
let person = {
name: '홍길동',
greet: function() {
console.log('안녕하세요, ' + this.name + '입니다.');
}
};
person.greet(); // 안녕하세요, 홍길동입니다.메서드 축약:
let person = {
name: '홍길동',
greet() {
console.log(`안녕하세요, ${this.name}입니다.`);
}
};
person.greet(); // 안녕하세요, 홍길동입니다.요약
- 템플릿 리터럴: 백틱(`)을 사용하여 문자열을 작성하고,
${}를 사용하여 변수나 표현식을 포함시킬 수 있습니다. - 태그드 템플릿 리터럴: 함수 뒤에 백틱을 사용하여 템플릿 리터럴을 호출할 수 있습니다.
- 객체 리터럴:
- 속성 축약: 변수와 속성명이 동일할 때, 축약형을 사용할 수 있습니다.
- 동적 속성 이름: 객체의 속성명을 동적으로 지정할 수 있습니다.
- 메서드 축약: 객체 내 함수 정의 시
function키워드를 생략할 수 있습니다.
19. 화살표 함수
화살표 함수(Arrow Function)와 기존 함수(Function)의 차이
자바스크립트에서는 함수 선언을 위해 기존의 function 키워드를 사용할 수 있고, 최신 문법에서는 더 간결한 화살표 함수(Arrow Function)를 사용할 수 있습니다.
하지만 화살표 함수가 기존의 function을 완벽히 대체하지는 않습니다.
두 가지 모두 사용해야 하는 상황이 있습니다.
화살표 함수 (Arrow Function)
화살표 함수는 더 간결한 문법을 제공합니다.
기본적인 사용법은 다음과 같습니다:
const add = (a, b) => {
return a + b;
};const add = (a, b) => a + b;화살표 함수와 기존 함수의 차이
this 바인딩
화살표 함수는 this 키워드를 함수가 정의된 위치의 this를 상속받습니다.
반면, 기존 함수는 자신만의 this를 가집니다.
function Person() {
this.age = 0;
setInterval(() => {
this.age++; // 화살표 함수: this는 Person 객체를 가리킴
console.log(this.age);
}, 1000);
}
const p = new Person();function Person() {
this.age = 0;
const that = this;
setInterval(function() {
that.age++; // 기존 함수: this를 that에 저장해 사용
console.log(that.age);
}, 1000);
}
const p = new Person();화살표 함수의 사용 규칙
매개변수가 하나인 경우 괄호 생략 가능
const square = x => x * x;매개변수가 없거나 둘 이상인 경우 괄호 필수
const greet = () => 'Hello'; const add = (a, b) => a + b;객체 리터럴 반환 시 괄호 필요
객체 리터럴을 반환할 때는 소괄호를 사용해야 합니다.
const getPerson = () => ({ name: 'John', age: 30 });
화살표 함수와 기존 함수 사용 시기
this를 사용하는 경우- 기존
function을 사용하여this가 함수마다 다르게 작동하도록 해야 하는 경우.
- 기존
간결하게 작성해야 하는 경우
- 간단한 콜백 함수나 리턴값이 바로 나오는 함수는 화살표 함수를 사용하는 것이 더 간결하고 가독성이 좋습니다.
예시: addEventListener
DOM 이벤트 핸들러를 사용할 때는 this가 중요합니다.
const button = document.querySelector('button');
button.addEventListener('click', function() {
console.log(this.textContent); // 기존 함수: this는 버튼 요소를 가리킴
});
button.addEventListener('click', () => {
console.log(this.textContent); // 화살표 함수: this는 상위 스코프의 this를 가리킴
});위 예시에서 화살표 함수는 상위 스코프의 this를 사용하기 때문에 예상한 동작을 하지 않을 수 있습니다.
결론
- 화살표 함수는 더 간결하고,
this를 상속받아 사용해야 할 때 유용합니다. - 기존 함수는 자신만의
this를 가져야 할 때 사용합니다.
20. 구조분해 할당
구조분해 할당은 객체나 배열에서 필요한 값을 쉽게 추출할 수 있도록 해주는 편리한 문법입니다.
이를 통해 코드가 더 간결해지고 가독성이 높아집니다.
객체의 구조분해 할당
const example = {
a: [1, 2, 3],
b: {
c: [1, 3, 5],
d: [1, 4, 6]
}
};
const a = example.a;
const d = example.b.d;
console.log(a); // [1, 2, 3]
console.log(d); // [1, 4, 6]const { a, b: { d } } = example;
console.log(a); // [1, 2, 3]
console.log(d); // [1, 4, 6]배열의 구조분해 할당
const array = [1, 2, 3, 4];
const x = array[0];
const y = array[1];
const z = array[3];
console.log(x); // 1
console.log(y); // 2
console.log(z); // 4const [x, y, , z] = [1, 2, 3, 4];
console.log(x); // 1
console.log(y); // 2
console.log(z); // 4객체 속성 이름 변경하기
구조분해 할당을 사용하여 객체의 속성 이름을 다른 변수 이름으로 변경할 수 있습니다.
const person = {
name: 'Alice',
age: 25
};
const { name: personName, age: personAge } = person;
console.log(personName); // 'Alice'
console.log(personAge); // 25구조분해 할당의 주의사항
this와의 문제
객체의 메서드에서 this를 사용하는 경우, 구조분해 할당을 잘못 사용하면 this가 의도한 대로 동작하지 않을 수 있습니다.
const candyMachine = {
status: {
name: 'node',
count: 5
},
getCandy() {
this.status.count--;
return this.status.count;
}
};
const { getCandy } = candyMachine;
console.log(getCandy()); // TypeError: Cannot read property 'count' of undefined위 예시에서는 this가 candyMachine 객체를 가리키지 않아서 오류가 발생합니다.
const candyMachine = {
status: {
name: 'node',
count: 5
},
getCandy() {
this.status.count--;
return this.status.count;
}
};
const { getCandy } = candyMachine;
const boundGetCandy = getCandy.bind(candyMachine);
console.log(boundGetCandy()); // 4결론
구조분해 할당을 사용하면 객체와 배열에서 필요한 값을 쉽게 추출할 수 있습니다.
이는 코드의 가독성과 간결성을 높여줍니다.
그러나 this를 사용하는 메서드에서 구조분해 할당을 사용할 때는 주의가 필요합니다.
이를 잘 활용하면 더 효율적이고 깔끔한 코드를 작성할 수 있습니다.
21. 클래스
자바스크립트 클래스와 프로토타입 이해하기
자바스크립트의 클래스(Class)는 프로토타입(Prototype)을 깔끔하게 만든 문법입니다.
클래스는 프로토타입 기반 객체지향 프로그래밍을 더 쉽게 작성할 수 있도록 도와줍니다.
클래스와 프로토타입의 차이와 상속을 이해하기 위해 기본적인 예제를 살펴보겠습니다.
프로토타입 기반 객체지향 프로그래밍
예시: 생성자 함수와 프로토타입 메서드
옛날에는 생성자 함수와 프로토타입을 사용하여 객체를 만들었습니다.
// 생성자 함수
function Human(name) {
this.name = name;
}
// 스태틱 메서드
Human.isHuman = function(obj) {
return obj instanceof Human;
};
// 인스턴스 메서드
Human.prototype.sayName = function() {
console.log(this.name);
};
// Human을 상속받는 생성자 함수
function Hero(name, alias) {
Human.call(this, name);
this.alias = alias;
}
// 상속
Hero.prototype = Object.create(Human.prototype);
Hero.prototype.constructor = Hero;
// 인스턴스 메서드 추가
Hero.prototype.sayAlias = function() {
console.log(this.alias);
};
// 객체 생성
const human = new Human('John');
const hero = new Hero('Superman', 'Clark Kent');
human.sayName(); // John
hero.sayName(); // Superman
hero.sayAlias(); // Clark Kent클래스 기반 객체지향 프로그래밍
ES6에서는 클래스를 도입하여 객체지향 프로그래밍을 더 쉽게 작성할 수 있습니다.
// 클래스 선언
class Human {
constructor(name) {
this.name = name;
}
// 스태틱 메서드
static isHuman(obj) {
return obj instanceof Human;
}
// 인스턴스 메서드
sayName() {
console.log(this.name);
}
}
// 상속
class Hero extends Human {
constructor(name, alias) {
super(name); // 부모 클래스의 생성자 호출
this.alias = alias;
}
// 인스턴스 메서드 추가
sayAlias() {
console.log(this.alias);
}
}
// 객체 생성
const human = new Human('John');
const hero = new Hero('Superman', 'Clark Kent');
human.sayName(); // John
hero.sayName(); // Superman
hero.sayAlias(); // Clark Kent주요 차이점
- 가독성: 클래스는 생성자 함수와 프로토타입 메서드를 하나의 블록으로 묶어 가독성을 높여줍니다.
- 상속: 클래스에서는
extends키워드를 사용하여 상속을 쉽게 구현할 수 있습니다.super를 사용하여 부모 클래스의 메서드를 호출할 수 있습니다. - 스태틱 메서드: 클래스 내에서
static키워드를 사용하여 스태틱 메서드를 정의할 수 있습니다.
프로토타입을 알아야 하는 이유
클래스는 프로토타입의 문법적인 설탕(syntactic sugar)입니다.
클래스 문법을 사용하더라도 내부적으로는 프로토타입을 기반으로 동작합니다.
따라서 프로토타입의 기본 개념을 이해하는 것이 중요합니다.
예를 들어, prototype 체인, 프로토타입 메서드, 생성자 함수 등을 이해하면 클래스 문법을 더 잘 활용할 수 있습니다.
결론
- 클래스: 더 깔끔하고 가독성 높은 문법으로 객체지향 프로그래밍을 쉽게 작성할 수 있게 해줍니다.
- 프로토타입: 클래스의 기초가 되는 개념으로, 자바스크립트의 객체지향 프로그래밍을 이해하는 데 필수적입니다.
22. Promise, async/await
자바스크립트의 프로미스(Promise)와 비동기 처리
프로미스는 자바스크립트의 비동기 작업을 관리하기 위한 객체입니다.
프로미스는 주로 네트워크 요청이나 파일 읽기 같은 비동기 작업을 처리할 때 사용됩니다.
프로미스의 기본 개념
프로미스는 다음 세 가지 상태를 가질 수 있습니다:
- 대기 중(
Pending): 아직 결과가 없는 초기 상태 - 이행됨(
Fulfilled): 작업이 성공적으로 완료되어 결과가 있는 상태 - 거부됨(
Rejected): 작업이 실패한 상태
프로미스는 비동기 작업이 완료되었을 때 그 결과를 처리하기 위해 .then()과 .catch() 메서드를 사용합니다.
const promise = new Promise((resolve, reject) => {
// 비동기 작업 수행
if (성공) {
resolve(결과); // 성공 시 결과 반환
} else {
reject(에러); // 실패 시 에러 반환
}
});
promise
.then((result) => {
// 성공 시 실행되는 코드
console.log(result);
})
.catch((error) => {
// 실패 시 실행되는 코드
console.error(error);
});function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const success = true; // 성공 여부
if (success) {
resolve('데이터 가져오기 성공');
} else {
reject('데이터 가져오기 실패');
}
}, 2000);
});
}
fetchData()
.then((data) => {
console.log(data); // '데이터 가져오기 성공'
})
.catch((error) => {
console.error(error); // '데이터 가져오기 실패'
});프로미스의 장점
- 콜백 헬(
Callbak Hell) 방지: 프로미스를 사용하면 콜백 함수의 중첩을 피할 수 있습니다. - 코드 분리: 프로미스는 비동기 작업을 수행하고 나중에 그 결과를 처리할 수 있게 해줍니다.
프로미스의 활용
여러 프로미스 처리
Promise.all(): 여러 프로미스를 병렬로 처리하고, 모든 프로미스가 완료될 때까지 기다립니다.Promise.allSettled(): 모든 프로미스가 완료될 때까지 기다리지만, 성공과 실패를 구분하지 않습니다.
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values); // [3, 42, 'foo']
});
Promise.allSettled([promise1, promise2, promise3]).then((results) =>
results.forEach((result) => console.log(result))
);
// {status: 'fulfilled', value: 3}
// {status: 'fulfilled', value: 42}
// {status: 'fulfilled', value: 'foo'}async/await
async/await는 프로미스를 더 쉽게 다룰 수 있도록 도와주는 문법입니다.async 함수는 항상 프로미스를 반환하며, await 키워드를 사용하여 프로미스가 완료될 때까지 기다릴 수 있습니다.
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('Error:', error);
}
}
fetchData();async/await의 장점
- 가독성: 코드가 동기 코드처럼 작성되어 가독성이 높아집니다.
- 에러 처리:
try...catch문을 사용하여 에러를 쉽게 처리할 수 있습니다.
결론
- 프로미스: 비동기 작업을 관리하기 위한 객체로,
.then()과.catch()메서드를 사용하여 결과를 처리합니다. async/await: 프로미스를 더 쉽게 다룰 수 있도록 도와주는 문법으로, 동기 코드처럼 작성할 수 있습니다.
23. Map, Set, WeakMap, WeakSet
자바스크립트의 맵(Map)과 셋(Set)
자바스크립트에는 맵(Map)과 셋(Set)이라는 객체가 있습니다.
이 객체들은 ES2015에서 도입되었으며, 더 간편하고 효율적인 데이터 구조를 제공합니다.
이 문법들은 자주 사용되며, 자바스크립트 개발에 있어 매우 유용합니다.
맵(Map)
맵은 키-값 쌍을 저장할 수 있는 객체입니다.
기존 객체(Object)와 다르게, 키로 문자열뿐만 아니라 다양한 타입을 사용할 수 있습니다.
또한, 삽입 순서를 기억합니다.
const map = new Map();
map.set('key1', 'value1');
map.set('key2', 'value2');
console.log(map.get('key1')); // 'value1'
console.log(map.has('key1')); // true
console.log(map.size); // 2
// 키-값 삭제
map.delete('key1');
// 모든 키-값 삭제
map.clear();
console.log(map.size); // 0맵의 특이점
- 맵은 객체를 키로 사용할 수 있습니다.
- 키와 값으로 다양한 데이터 타입을 지원합니다.
- 삽입된 순서를 기억합니다.
const objKey = {name: 'object'};
const map = new Map();
map.set(objKey, 'objectValue');
console.log(map.get(objKey)); // 'objectValue'셋(Set)
셋은 중복되지 않는 값을 저장할 수 있는 객체입니다.
배열과 비슷하지만, 중복을 허용하지 않는다는 점에서 차이가 있습니다.
// 생성:
const set = new Set();
// 값 추가:
set.add(1);
set.add(2);
set.add(2); // 중복된 값은 무시됨
// 값 존재 여부 확인:
console.log(set.has(1)); // true
console.log(set.has(3)); // false
// 값 삭제:
set.delete(2);
// 모든 값 삭제:
set.clear();
// 셋의 크기 확인:
console.log(set.size); // 0맵과 셋의 활용
맵과 셋은 각각 객체와 배열을 대체하거나 보완할 수 있는 기능을 제공합니다.
중복 제거
셋을 사용하면 배열의 중복된 값을 쉽게 제거할 수 있습니다.
const array = [1, 2, 2, 3, 4, 4, 5];
const set = new Set(array);
const uniqueArray = Array.from(set);
console.log(uniqueArray); // [1, 2, 3, 4, 5]데이터 매핑
맵을 사용하면 객체 키를 문자열뿐만 아니라 객체, 숫자 등 다양한 타입으로 사용할 수 있어 데이터 매핑이 더 유연해집니다.
const map = new Map();
map.set(1, 'one');
map.set('2', 'two');
map.set({}, 'object');
console.log(map.get(1)); // 'one'
console.log(map.get('2')); // 'two'위크맵(WeakMap)과 위크셋(WeakSet)
위크맵과 위크셋은 가비지 컬렉션(Garbage Collection)을 돕기 위한 객체입니다.
객체를 참조하지만, 그 객체가 가비지 컬렉션 대상이 되면 자동으로 정리됩니다.
위크맵(WeakMap)
위크맵은 객체를 키로 사용할 수 있으며, 객체가 메모리에서 삭제될 때 자동으로 정리됩니다.
const weakMap = new WeakMap();
let obj = {};
weakMap.set(obj, 'value');
console.log(weakMap.get(obj)); // 'value'
obj = null; // obj가 메모리에서 삭제되면 weakMap에서 자동으로 삭제됨
weakMap.get(obj); // undefined위크셋(WeakSet)
위크셋은 객체의 집합을 저장할 수 있으며, 객체가 메모리에서 삭제될 때 자동으로 정리됩니다.
const weakSet = new WeakSet();
let obj = {};
weakSet.add(obj);
console.log(weakSet.has(obj)); // true
obj = null; // obj가 메모리에서 삭제되면 weakSet에서 자동으로 삭제됨
weakSet.has(obj); // false결론
- 맵(
Map): 키-값 쌍을 저장하고 관리하는 객체로, 객체, 배열 등의 다양한 타입을 키로 사용할 수 있습니다. - 셋(
Set): 중복되지 않는 값을 저장하는 객체로, 배열에서 중복을 제거할 때 유용합니다. - 위크맵(
WeakMap)과 위크셋(WeakSet): 가비지 컬렉션을 지원하는 객체로, 메모리 관리에 도움을 줍니다.
24. 옵셔널 체이닝, 널 병합
널 병합 연산자와 옵셔널 체이닝은 ES2020에 추가된 자바스크립트 문법입니다.
이 두 문법은 코드를 간결하고 안전하게 만드는 데 큰 도움이 됩니다.
이미 TypeScript나 Babel을 사용하시는 분들은 익숙할 수 있지만, 아직 사용하지 않은 분들을 위해 각각의 문법을 자세히 설명하겠습니다.
널 병합 연산자 (Nullish Coalescing Operator)
널 병합 연산자는 ?? 연산자로 표현되며, || 연산자와 유사하지만 중요한 차이점이 있습니다.|| 연산자는 false 값을 만나면 오른쪽 값을 반환하는 반면, ?? 연산자는 null이나 undefined 값을 만났을 때만 오른쪽 값을 반환합니다.
let a = 0;
let b = a || 3; // b는 3이 됩니다. 0은 false로 간주되기 때문입니다.
let c = a ?? 3; // c는 0이 됩니다. 0은 null이나 undefined가 아니기 때문입니다.let count = 0;
let result = count ?? 10; // result는 0이 됩니다. count는 null이나 undefined가 아니기 때문입니다.옵셔널 체이닝 (Optional Chaining)
옵셔널 체이닝 연산자는 ?.로 표현되며, 객체의 속성에 접근할 때 해당 속성이 null이나 undefined인 경우 에러를 방지하고 undefined를 반환합니다.
이는 코드에서 흔히 발생하는 "Cannot read property of undefined"와 같은 에러를 방지하는 데 매우 유용합니다.
let user = {
address: {
street: '123 Main St'
}
};
let street = user?.address?.street; // street는 '123 Main St'가 됩니다.
let city = user?.address?.city; // city는 undefined가 됩니다. 에러가 발생하지 않습니다.let user = {
greet: function() { console.log('Hello'); }
};
user?.greet?.(); // 'Hello'를 출력합니다. greet 함수가 존재하지 않으면 undefined를 반환합니다.옵셔널 체이닝과 널 병합 연산자 조합
이 두 문법을 함께 사용하면 더욱 강력합니다.
예를 들어, 중첩된 객체에서 값을 안전하게 접근하고 기본 값을 설정하는 경우입니다.
let user = {
settings: {
theme: 'dark'
}
};
let theme = user?.settings?.theme ?? 'default'; // theme은 'dark'가 됩니다.
let language = user?.preferences?.language ?? 'en'; // language는 'en'이 됩니다. preferences가 undefined이기 때문입니다.요약
- 널 병합 연산자(
??)는null이나undefined일 때만 오른쪽 값을 반환합니다. - 옵셔널 체이닝(
?.)은 객체 속성에 접근할 때 해당 속성이null이나undefined이면undefined를 반환하고, 에러를 방지합니다. - 두 문법을 함께 사용하면 코드를 더욱 간결하고 안전하게 작성할 수 있습니다.
25. 프런트엔드에서 자주 사용하는 자바스크립트
AJAX 요청: Axios 사용하기
AJAX 요청은 웹페이지에서 서버로 데이터를 비동기적으로 요청할 때 사용됩니다.
예전에는 XMLHttpRequest를 많이 사용했지만, 요즘은 더 간단하고 직관적인 라이브러리인 Axios를 많이 사용합니다.
Axios 사용법
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
axios.get('https://example.com/api/data')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Error fetching data:', error);
});
</script>POST 요청 보내기
POST 요청은 데이터를 서버에 전송할 때 사용됩니다.
예를 들어, 로그인 정보를 서버로 보내는 경우에 사용합니다.
<script>
axios.post('https://example.com/api/login', {
username: 'your_username',
password: 'your_password'
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Error logging in:', error);
});
</script>FormData 객체
파일 업로드 등과 같은 작업을 할 때는 FormData 객체를 사용합니다.FormData 객체는 폼 데이터를 쉽게 생성하고 전송할 수 있게 해줍니다.
<script>
let formData = new FormData();
formData.append('file', document.querySelector('input[type="file"]').files[0]);
axios.post('https://example.com/api/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Error uploading file:', error);
});
</script>이 예제에서는 파일 입력 요소에서 선택된 파일을 FormData 객체에 추가하고, 서버로 POST 요청을 보냅니다.
URL 인코딩: encodeURIComponent와 decodeURIComponent
URL에 한글이나 특수 문자가 포함될 때는 인코딩이 필요합니다.
이를 위해 encodeURIComponent와 decodeURIComponent 함수를 사용합니다.
<script>
let originalText = '안녕하세요';
let encodedText = encodeURIComponent(originalText);
console.log(encodedText); // %EC%95%88%EB%85%95%ED%95%98%EC%84%B8%EC%9A%94
let decodedText = decodeURIComponent(encodedText);
console.log(decodedText); // 안녕하세요
</script>이 예제에서는 한글 텍스트를 URL에 안전하게 포함할 수 있도록 인코딩하고, 다시 디코딩하여 원래 텍스트로 복원합니다.
HTML 데이터 속성
HTML 요소에 데이터 속성을 추가하여 자바스크립트에서 접근할 수 있습니다.
예를 들어, 특정 요소에 사용자 정보를 저장할 수 있습니다.
<div id="user" data-name="John Doe" data-age="30"></div>
<script>
let userElement = document.getElementById('user');
let userName = userElement.dataset.name;
let userAge = userElement.dataset.age;
console.log(`Name: ${userName}, Age: ${userAge}`); // Name: John Doe, Age: 30
</script>이 예제에서는 data-name과 data-age 속성을 사용하여 사용자 정보를 저장하고, 자바스크립트에서 이 정보를 가져와서 출력합니다.