HTML,CSS와 함께 주로 웹 브라우저에서 동작하는 프로그래밍 언어
이다. HTML은 '브라우저의 구조와 정보'를, CSS는 '브라우저 스타일링'을, 자바스크립트는 '브라우저의 움직임'을 담당한다.간단한 문법
을 가지고, 클라이언트 개발은 물론 서버 개발에도 사용할 수 있어 범용성
이 뛰어나다. 다만 유연한 언어
이기 때문에 코드에 문제가 있어도 실행되는 경우가 있어 디버깅이 어려워질 수 있다. (Strict Mode, TypeScript로 보완 가능)Call Stack과 Memory Heap
으로 구성되어 있다. Call Stack은 원시 타입의 데이터와 실행 컨텍스트
를 저장하는 곳이고, Memory Heap은 참조 타입의 데이터
을 저장하는 곳이다.자바스크립트 표준 사양을 정의하는 규약
이다.2015넨에 발표된 자바스크립트 표준 사양을 정의하는 규약의 여섯 번째 버전
이다. 이 버전은 자바스크립트에 여러 중요 기술들을 도입
한 중요한 버전이다.
ES6 주요 변경점
- let, const
- 화살표 함수
- Promise
- 클래스
- import, export를 사용하는 모듈 시스템
- 각종 리터럴 (문자열 리터럴, 객체 리터럴, 템플릿 리터럴)
- 전개 연산자, 구조 분해 할당
- Symbol, Map, Set
- ...
require와 import
모듈을 불러올 때 사용하는 키워드
이다.
- require:
(NodeJS에서 사용되고 있는)CommonJS 키워드
.동기적
으로 모듈을 불러옴. 내보낼 때는module.exports 혹은 exports
사용.- import:
ES6에 도입된 키워드
.비동기적
으로 모듈을 불러옴. 내보낼 때는export default 혹은 export
사용.
값을 저장하는 메모리 공간
을 의미하고 식별자는 그 메모리 공간의 이름
을 의미한다.메모리 공간을 확보하고 해당 메모리 공간의 주소와 식별자를 연결하는 작업
이고, 할당은 메모리 공간에 데이터을 저장하는 작업
이다. 선언과 할당이 동시에 일어나는 작업
을 초기화하고 한다.렉시컬 스코프의 선언이 스코프 최상단으로 끌어올려지는 현상
이다. 자바스크립트 엔진
은 실행 컨텍스트를 생성 단계
에서 실행에 필요한 변수와 함수들을 메모리 공간에 등록
하는데, 이 작업으로 인해 선언 위치에 상관없이 해당 변수와 함수에 접근이 가능
해진다.ES6 이전부터 변수를 선언하기 위해 사용되던 키워드
이고 let과 const는 ES6에서 var의 단점을 보완하고자 등장한 키워드
이다. / var는 자바스크립트 엔진에 의해 undefined로 자동으로 초기화되므로 호이스팅 시 undefined가 출력
되지만, let과 const는 초기화 작업을 거치지 않아 호이스팅 시 ReferenceError(undeclared)가 출력
된다. 또한 var은 함수만을 지역 스코프로 인정
하는 함수 레벨 스코프를 가지지만 let과 const는 함수를 포함한 모든 블록을 지역 스코프로 인정
하는 블록 레벨 스코프를 가진다. 그리고 var은 재선언이 가능
하지만 let과 const는 재선언이 불가능
하다. / 이러한 특징을 보았을 때, 코드를 명시적으로 작성하기 위해서 var보다 let과 const를 사용하는 것이 유리하다.재할당이 가능
(초기화하지 않아도 OK)하고, const는 재할당이 불가능
(초기화가 필수)하다 자바스크립트의 데이터 타입으로는 원시 타입과 참조 타입(객체 타입)
이 있다. / 원시 타입은 변경 불가능한 값으로 immutable 특성
을 가지며 number, string, boolean, null, undefined, symbol 등이 있다. 참조 타입은 변경 가능한 값으로 mutable 특성
을 가지며 원시 타입을 제외한 모든 것(object, array, function 등)이 참조 타입이다.
immutable/mutable의 개념 vs 재할당의 개념
immutable/mutable은
메모리 공간에 있는 데이터의 안에 들어있는 값
이 변경될 수 있는지에 대한 개념이고, 재할당은메모리 공간에 있는 데이터
가 변경되는 개념이다.
null, undefined, undeclared, NaN
null은 '빈 값', undefined는 '정의되지 않음', undeclared는 '선언되지 않음', NaN은 '표현 불가능한 수치 결과'를 의미한다.
symbol(ES6)
객체의 키로 사용되는 자료형
이다.같은 문자열로 생성하더라도 각각의 고유성을 보장하여 이름 충돌을 방지
할 수 있고,문자열을 은폐할 수 있어 키 값의 외부 노출을 방지
할 수 있다. (for key in Object, Object.keys, Object.entries에서도 출력되지 않음!)
정적 타이핑과 동적 타이핑
이 있다. / 정적 타이핑이란 변수 선언 시
타입을 결정하는 방식이다. (해당 타입의 값만 할당할 수 있음) 한편 동적 타이핑이란 변수 선언이 아닌 변수에 값이 할당될 때
타입을 결정하는 방식이다. (값과 타입이 변할 수 있음) 타입 변환 방식에는 명시적 타입 변환과 암묵적 타입 변환
이 있다. / 명시적 타입 변환은 Number(), String() 등의 메서드나 NOT 연산자 등을 통해 개발자가 직접 타입을 변환
하는 방식이다. 한편 암묵적 타입 변환은 자바스크립트 엔진에 의해 자동으로 타입이 변환
되는 방식이다.
암묵적 타입 변환의 예시
문자열과 숫자 타입의 값에 더하기 연산자를 사용했을 때는 문자열로, 빼기/곱하기/나누기 연산자를 사용했을 때 숫자로 변환된다.
조건문이나 논리 연산
에서 true로 평가되는 값
은 truthy, false로 평가되는 값
은 falsy라고 한다. / falsy에는 false, undefined, null, 0, -0, NaN, 빈 문자열('')
등이 속하고 나머지
는 truthy에 속한다.여러 값을 index를 통해 저장하는 데이터
이다.크기와 타입이 동일한 값이 연속적으로 나열되는 밀집 배열
과 크기와 타입이 달라도 되고 연속적이지 않아도 되는 희소 배열
이 있는데, 자바스크립트의 배열은 희소 배열이다.원본 배열을 변경하는 메서드로 push, pop, unshift, shift, splice, sort, reverse 등
이 있고, 원본 배열을 변경하지 않는 메서드로 '고차 함수 배열 메서드', slice, concat 등
이 있다. 고차 함수인 배열 매서드는 forEach, map, every, some, find, reduce
처럼 콜백 함수를 갖는 메서드이다.
split과 join
split은
문자열을 특정 구분자를 기준으로 나누어 배열로 반환
하고, join은배열의 요소들을 특정 구분자로 연결하여 문자열로 반환
한다.
두 메서드 모두 배열을 순회하며 각 요소에 대해 콜백 함수를 실행
하는 메서드이다. forEach는 undefined
를 반환하지만, map은 콜백 함수의 반환값으로 이루어진 배열
을 반환한다.
for in vs for of
for in 루프 -
enumerable한, 열거 가능한 데이터
를 순회하는 반복문
for of 루프 -iterable한, 반복 가능한 데이터
를 순회하는 반복문
키와 값으로 구성된 프로퍼티를 저장하는 데이터
이다. 자바스크립트 엔진에 의해 생성되는 어디에서든지 접근 가능한 특수 객체
이다.표준 빌트인 객체, 호스트 객체, 사용자 정의 객체
를 프로퍼티
로 가진다.window
가, NodeJS 환경에서는 global
이 전역 객체이다.표준 빌트인 객체와 호스트 객체
표준 빌트인 객체(Object, Map, Set, Promise, Math, Date, RegExp...)는
ECMAScript 사양으로 정의된 객체
이고, 호스트 객체(window, global, document...)는자바스크립트 실행 환경에서 제공하는 객체
이다.
원시 타입의 데이터를 객체 타입처럼 사용해야 하는 경우
, 자바스크립트 엔진
은 원시 타입의 데이터를 일시적으로 연관된 객체로 변경하여 사용
하는데, 이 때 사용하는 객체를 래퍼 객체라고 한다.iterable한 특성을 가지는 Keyed Collection
이다. / Map은 문자열, 심볼뿐만 아니라 다양한 타입의 key를 허용하는 Collection
이고, Set은 value만을 저장하며 중복값을 허용하지 않는 Collection
이다. (key를 따로 저장하지는 않지만 value값이 곧 key값이 된다.)파라미터에 원시 타입을 할당하여 함수를 호출
한다면 데이터의 원본값(값이 '담긴' 주소값)을 복사하여 전달
하고, 이를 'call by value(값에 의한 호출)'라고 한다. 원시 타입은 immutable한 특성
을 가지기 때문에, 함수가 전달받은 데이터를 변경한다고 하더라도 기존 데이터는 변경되지 않는다. / 반면 참조 타입을 할당하여 함수를 호출
한다면 데이터의 주소값(값이 '담긴 곳을 가르키는' 주소값)을 복사하여 전달
하는데, 엄밀히 말하자면 이는 데이터의 주소값을 그대로 전달하는 'call by reference(참조에 의한 호출)'와는 다르기 때문에 자바스크립트는 call by value의 개념만 존재한다고 할 수 있다. (참조 타입의 경우, call by sharing이라는 용어를 사용해서 call by reference와 구분한다.) 한편 참조 타입은 mutable한 특성
을 가지기 때문에, 함수가 전달받은 데이터를 변경(ex: 프로퍼티에 접근하여 값을 변경하는 방식
)한다면 기존 데이터가 변경된다. 다만 새로운 참조 데이터를 생성하여 값을 할당하는 방식
으로 전달받은 데이터를 변경한다면 새로운 주소값을 사용하기 때문에 기존 데이터가 유지된다.특정 작업을 수행하는 재사용 가능한 코드 블록
이다. 함수 본연의 입출력 기능을 직관적으로 보여주면서 간단하게 정의할 수 있는 함수 정의 방법
이다.화살표 함수의 this
는 언제나 함수가 선언될 때의 렉시컬 환경, 즉 상위 스코프에서의 this 바인딩 규칙
을 따른다. 이를 렉시컬 this
라고 한다.파라미터가 하나라면
소괄호를, 반환문 한 줄만 존재한다면
중괄호를 생략할 수 있다.)function 키워드를 맨 앞에 바로 선언하는 방식
으로, 이렇게 선언된 함수는 실행 컨택스트 생성 단계에서 메모리 공간에 등록
된다. 이에 따라 함수 호이스팅이 일어나기 때문에, 선언부 이전 호출 시 함수가 실행
된다. / 반면 함수 표현식은 함수를 생성하여 변수에 할당하며 선언하는 방식
으로, 함수 호이스팅이 일어나지 않고 변수 호이스팅이 일어나기 때문에, 함수 선언부 이전 호출 시 TypeError 혹은 undefined가 출력
된다.선언과 동시에 단 한번만 실행되는 함수
이다. 전역 변수 생성을 줄이고자 할 때, 변수를 은닉하고자 할 때
사용할 수 있다.식별자가 유효한 범위
이다.스코프는 전역 스코프와 지역 스코프
로 구분할 수 있다. / 전역 스코프는 가장 바깥 영역의 스코프
로 어떤 환경에서든지 접근
할 수 있고, 지역 스코프는 함수나 블록의 스코프
로, 해당 함수나 블록 내부에서만 접근
할 수 있다.
전역 변수 선언의 문제점
전역 변수를 선언한다는 것은 전역 스코프를 사용한다는 것인데, 전역 스코프를 사용하면
어디서든 참조될 수 있
고,생명 주기가 길기 때문에 오랫동안 변경될 수 있
다. 또한스코프 체인의 끝에 있으므로 속도가 느리
다.
정적 스코핑과 동적 스코핑
으로 나뉜다. / 정적(렉시컬) 스코핑은 함수 선언 시
스코프를 결정하는 방식이고, 동적 스코핑은 함수 호출 시
스코프를 결정하는 방식이다. / 자바스크립트는 정적 스코핑을 통해 스코프를 결정한다.클로저는 함수와 그 함수가 선언될 때의 렉시컬 환경의 조합
으로, 자신이 선언될 때의 렉시컬 환경을 기억하는 함수
를 클로저 함수라고 한다. / 클로저는 함수 내부에서 또 다른 함수를 정의하고 해당 함수를 리턴하는 형태
를 가진다. 이렇게 되면, 외부 함수가 종료되더라도 내부 함수는 렉시컬 환경에 계속 접근할 수 있다
. / 이를 통해 변수의 캡슐화
와 상태 유지
를 구현할 수 있다.
(클로저는 메모리를 계속 차지
한다는 단점이 있다.)
클로저를 사용한 캡슐화 예시
function getPassword() { const password = "mySuperSecretPassword"; function getPasswordClosure() { return password; } return getPasswordClosure; } console.log(getPassword()); // [Function: getPasswordClosure] const getPasswordFunction = getPassword(); console.log(password); // ReferenceError: password is not defined console.log(getPasswordFunction()); // "mySuperSecretPassword"
클로저를 사용한 캡슐화 예시
function createCounter() { let count = 0; // 카운트 상태 유지 return function () { count++; // 카운트 증가 return count; // 현재 카운트 값 반환 }; } const counter1 = createCounter(); console.log(counter1()); // 1 console.log(counter1()); // 2 console.log(counter1()); // 3 const counter2 = createCounter(); console.log(counter2()); // 1 console.log(counter2()); // 2 console.log(counter2()); // 3
new 키워드로 호출하는 함수
이다. / String, Number, Boolean 등의 빌트인 생성자 함수
를 사용할 수도 있고 사용자 정의 함수
를 사용할 수도 있다.하나의 객체를 간편하게 생성
할 수 있다. / 생성자 함수는 동일한 구조의 여러 객체를 생성
하는데 유리하다. / ES6의 클래스를 사용하면 동일한 구조의 여러 객체를 생성할 수 있는 것은 물론 extends를 사용하여 쉽게 상속을 구현
할 수 있다. (가독성 측면에서도 유리)생성자 함수를 선언
new 키워드를 통해 생성자 함수를 호출
하여 this를 바인딩하고 인스턴스를 초기화
생성자 함수가 실행
되며 인스턴스 반환
생성 예시
function Workout(name, sets, reps) { this.name = name; this.sets = sets; this.reps = reps; this.getInfo = function () { console.log( `오늘의 운동은 ${this.name}이고 ${this.sets}세트, 각 ${this.reps}회가 목표입니다!` ); }; } let squat = new Workout("Squat", 3, 5); let legPress = new Workout("Leg Press", 5, 10); squat.getInfo(); // 오늘의 운동은 Squat이고 3세트, 각 5회가 목표입니다! console.log(squat.constuctor) // Workout legPress.getInfo(); // 오늘의 운동은 Leg Press이고 5세트, 각 10회가 목표입니다! console.log(legPress.constuctor) // Workout
자신이 속한 객체 혹은 생성할 인스턴스
를 가리키는 자기 참조 변수이다.this와 this가 가르킬 객체를 연결하는 작업
을 this 바인딩이라고 한다.암시적 바인딩 ('일종의 바인딩 규칙')
- 전역이나 일반 함수
에서의 this는 전역 객체
를 가르킨다.
- 메서드
에서의 this는 자신이 속한 객체
를 가르킨다.
- 생성자 함수
에서의 this는 생성할 인스턴스
를 가르킨다.
- (이벤트 리스너의 콜백 함수
에서 사용되는 경우는 이벤트가 발생한 요소
를 가르킨다.)
명시적 바인딩 ('사용자가 직접 바인딩')
- call, apply, bind 라는 메서드를 통해 this가 메서드의 첫 번째 인자로 들어온 객체
를 가르키도록 할 수 있다. / (call은 매개변수를 함께 전달
하여 사용하고 apply는 매개변수를 배열 형태로 함께 전달
하여 사용한다. bind는 해당 객체로 바인딩된 함수를 리턴하므로, 반환된 함수에 매개변수를 전달
하여 사용한다.)
기타
- 화살표 함수의 this
는 언제나 함수가 선언될 때의 환경, 즉 상위 스코프
에서의 this 바인딩 규칙을 따른다. 이를 렉시컬 this
라고 한다.
명시적 바인딩 메서드 사용법
const workout = { name: "Squat", todayWorkout: function () { return `오늘의 운동: ${this.name} / `; }, }; function getInfo(kg, sets, reps) { return this.todayWorkout() + `${kg}KG ${sets}SETS ${reps}REPS`; } const strengthTraining = getInfo.call(workout, 140, 3, 5); console.log(strengthTraining); // 첫 번째 매개변수에는 "this가 가리킬 객체" // 두 번째 매개변수부터 "함수의 매개변수"를 입력 ! // 오늘의 운동: Squat / 140KG 3SETS 5REPS const hypertrophyTraining = getInfo.apply(workout, [100, 3, 12]); console.log(hypertrophyTraining); // 첫 번째 매개변수에는 "this가 가리킬 객체" // 두 번째 매개변수에는 "함수의 매개변수를 배열로" 입력 ! // 오늘의 운동: Squat / 100KG 3SETS 12REPS const endurance = getInfo.bind(workout); const enduranceTraining = endurance(80, 3, 20); console.log(enduranceTraining); // 매개변수로 "this가 가리킬 객체"를 입력하고 // 함수의 매개변수는 리턴받은 함수를 호출할 때 입력 ! // 오늘의 운동: Squat / 80KG 3SETS 20REPS
바인딩 우선순위
생성할 인스턴스로 바인딩(in 생성자 함수) > 명시적 바인딩 > 자신이 속한 객체에 바인딩(in 메서드)
함수를 일급 객체 취급하고 외부 상태에 의존하지 않는 순수 함수를 사용
하여 사이드 이펙트를 줄이고 참조 투명성을 지키는
프로그래밍 페러다임이다.
이름없는 리터럴로 생성 가능
변수나 자료 구조에 저장 가능
다른 함수의 매개변수나 반환값으로 사용 가능
함수형 프로그래밍의 등장 배경
- 전역 변수 선언(전역 스코프 사용)의 '어디에서든지 참조될 수 있고, 오랫동안 변경될 수 있으며, 느리다는 단점'이 부각됨.
- 스코프의 범위를 클래스로 좁히는 객체 지향 프로그래밍 등장. (공통으로 사용하는 변수를 자기들끼리만 사용하는 특징을 가짐.)
- 초기 자바스크립트에서는 클래스의 개념이 없었기 때문에 OOP 구현이 제한적. 따라서 스코프의 범위를 함수로 좁히는 함수형 프로그래밍 등장. (공통으로 사용하는 변수를 아예 사용하지 않는 특징을 가짐.)
프로그래밍에 필요한 개념을 객체라는 개념으로 추상화
하고 객체들의 상호작용을 통해 프로그래밍
하는 프로그래밍 패러다임이다.복잡한 개념을 공통된 핵심 기능으로 묶어 단순화
하는 것기존 객체의 기능을 다른 객체가 사용할 수 있도록 전달
하는 것같은 이름의 메서드가 다양한 형태로 동작
할 수 있도록 하는 것데이터를 외부로부터 보호
하는 것멀티 패러다임 프로그래밍 언어
이다. ES6 이후 클래스가 도입되어 클래스를 이용한 객체 지향 프로그래밍이 가능
해졌지만 자바스크립트는 여전히 클래스 기반이 아닌 프로토타입 기반 언어
이고, 여러가지 프로그래밍 패러다임을 지향
하기 때문이다.생성자 함수와 프로토타입 메서드
를 사용하거나 (ES6의) 클래스
를 통해 구현할 수 있다.자바스크립트는 프로토타입 기반 언어
로, 모든 객체는 프로토타입이라는 쌍둥이 객체를 가지고 있다. 원본 객체와 프로토타입 객체는 각각 constructor와 prototype이라는 프로퍼티를 통해 상호 참조하여 연결
되어 있고, 원본 객체는 __proto__라는 프로퍼티를 통해 프로토타입 링크를 타고 상위의 프로토타입 객체와 연결
된다. 이러한 연결고리를 '프로토타입 체인'이라고 하고, 이를 통해 객체는 상위 객체에서도 필요한 프로퍼티를 찾을 수 있다.자바스크립트에서 OOP를 구현하기 위해 ES6에 추가된 문법
이다. 클래스를 사용하면 여러 객체를 쉽게 찍어낼 수 있
고, extends 키워드를 통해 상속을 구현할 수 있
다.class 키워드
를 사용하여 선언
하고, constructor 내부
에서 프로퍼티를 정의
하고 constructor 외부
에서 메서드를 정의
한다. 그리고 new 키워드
를 통해 인스턴스를 생성
한다.유연한 언어인 자바스크립트를 엄격한 환경에서 실행하는 모드
로, 자바스크립트에서 에러가 더 잘 발생되도록 한다.전역 변수 암묵적 선언 불가
, 재선언 금지
, 함수 내부 this에 직접 값 할당 불가
등클래스 내부의 body
는 Strict Mode로 실행된다.)자바스크립트 엔진이 생성
한 코드 실행에 필요한 정보를 모아놓은 환경
이다. 애플리케이션이 시작할 때 한번만 생성
되고 애플리케이션이 종료될 때까지 유지
된다. 이는 자바스크립트가 싱글 스레드 언어라는 것을 의미한다. 함수 실행 컨텍스트는 함수가 호출될 때마다 생성
되고 해당 함수의 실행이 완료될 때까지 유지
된다. 함수를 호출했지만 아직 실행되지 않은 단계
이고, 실행 단계는 함수가 실행되는 단계
이다. / 생성 단계에서는 변수 환경과 렉시컬 환경이 생성
되며 this 바인딩
이 일어난다.환경 레코드(Environment Record)
와 외부 환경 참조(Outer environment reference)
라는 동일한 프로퍼티
를 가진다. / 환경 레코드에는 실행에 필요한 변수와 함수
를 등록하여 호이스팅이 일어날 수 있는 환경을 형성
하고, 외부 환경 참조에는 외부 스코프에 대한 참조 정보
를 등록하여 스코프 체인을 형성
한다. / 다만 변수 환경의 환경 레코드
에는 초기화까지 이루어지는 var, 함수선언식으로 선언된 식별자
가 등록되고, 렉시컬 환경의 환경 레코드
에는 초기화되지 않는 let, const로 선언된 식별자
가 등록된다. / (let과 const가 등장함에 따라 관련 정보를 저장하기 위해 렉시컬 환경이라는 쌍둥이 프로퍼티가 등장한 것이라는 추측성 글을 본 적이 있다.)동등 연산자
로, 자동으로 형변환을 수행하여 타입을 고려하지 않고 값을 비교한다. 반면 '==='는 일치연산자
로 형변환을 수행하지 않아 타입을 고려하여 값을 비교한다. iterable 특성을 가지는(=반복 가능한) 데이터를 펼쳐놓는 문법
이다. / 배열, 문자열, Map, Set 등
에 사용할 수 있고, 예외적으로 객체 리터럴
에도 적용할 수 있다. / 리액트에서 state 불변성을 유지를 위해 참조 타입의 데이터를 복사
할 때 자주 사용한다.
const initialState = { count: 0 };
const newState = { ...initialState, count: initialState.count + 1 };
console.log(newState); // { count: 1 }
배열이나 객체 등의 데이터를 분해하여 새로운 배열이나 객체에 할당하는 문법
이다. / 리액트에서 props를 전달받아서 데이터를 추출
할 때 자주 사용한다.
// 부모 컴포넌트
const ParentComponent = () => {
const userData = { username: 'john', email: 'john@example.com', isAdmin: true };
return (
<div>
<UserInfo userData={userData} />
</div>
);
}
// 자식 컴포넌트
const UserInfo = ({ userData }) => {
const { username } = userData;
return (
<div>
<p>Username: {username}</p>
</div>
);
}
나머지 요소를 추출하기 위한 문법
이다. / 구조 분해 할당 시 스프레드 연산자를 같이 사용
하면 추출하지 않은 나머지 요소를 한번에 추출
할 수 있다.
// 부모 컴포넌트
const ParentComponent = () => {
const userData = { username: 'john', email: 'john@example.com', isAdmin: true };
return (
<div>
<UserInfo userData={userData} />
</div>
);
}
// 자식 컴포넌트
const UserInfo = ({ userData, ...rest }) => {
const { username } = userData;
return (
<div>
<p>Username: {username}</p>
{/* 나머지 속성들을 출력 */}
<p>Other Data: {JSON.stringify(rest)}</p>
</div>
);
}
자바스크립트 v8 엔진으로 빌드된 자바스크립트 런타임(실행환경)
이다. 단일 스레드(단일한 콜스택)
를 가지면서 논블로킹 I/O를 지원하여 비동기 처리가 가능
하다는 특징이 있다.Node.js 환경
에서 자바스크립트 라이브러리를 설치 및 관리하는 패키지 매니저이다. 패키지를 순차적으로 처리
하고, 패키지에 포함된 다른 패키지를 자동으로 설치
하는 특징을 가진다.
yarn
페이스북
에서 개발한 자바스크립트 라이브러리를 설치 및 관리하는 패키지 매니저이다. 패키지를병렬적으로 처리
(속도가 더 빠름)하고,yarn.lock 또는 package.json 파일에 있는 패키지만을 설치
(안정성 및 보안성 개선)하는 특징을 가진다.
웹 페이지에서 발생하는 상황이나 상호작용
을 의미한다.HTML의 Attribute 조작
DOM API로 Property 조작
어떤 요소에 이벤트가 발생할 때, 이벤트가 DOM 트리를 통해 다른 요소로 전파되는 현상
이다. / 이벤트 전파는 캡처링 단계 - 타겟 단계 - 버블링 단계
를 거친다. / 캡처링 단계는 상위 요소에서부터 타겟 요소로 이벤트가 전파
되는 단계이고, 타겟 단계는 이벤트가 타겟 요소에 도달하여 이벤트 핸들러가 실행
되는 단계이고, 버블링 단계는 타겟 요소에서부터 다시 상위 요소로 이벤트가 전파
되는 단계이다.
event.target과 event.currentTarget 차이점
이벤트가 발생한 요소
가 event.target이고,이벤트 핸들러가 등록된 요소
가 event.currentTarget이다.
기본적으로 이벤트 버블링 단계에서 이벤트가 처리되도록 설정
되어 있고, addEventListener의 세 번째 인자에 true를 입력하면 버블링이 아닌 캡처링 단계로 설정
된다. 한편 이벤트 핸들러에 event.stopPropagation을 추가하면 이벤트 전파를 중단
할 수 있다.
event.preventDefault
이벤트의 기본 동작을 막는 메서드
이다.
이벤트 버블링을 활용
하여 여러 요소에 이벤트 핸들러를 등록할 때 공통 부모 요소에만 등록
하여 메모리 낭비를 방지
하는 방법이다.연속적으로 일어나는 이벤트의 과도한 호출을 방지
하기 위한 기술이다. / debounce는 일정 시간동안 이벤트가 발생하지 않으면 마지막 이벤트를 처리하는 기술
이고, throttle은 일정 시간동안 일어난 이벤트를 1번만 처리하는 기술
이다.순차적으로 작업을 처리
하는 것이고, 비동기는 이전 작업이 끝나지 않더라도 다음 작업을 병렬적으로 처리
하는 것을 말한다.함수의 실행 결과가 즉시 반영되지 않고 특정 조건이 충족될 때까지 기다리는 함수
이다. 비동기 동작을 위해 타이머 함수처럼 콜백 함수를 사용
할 수도 있고, fetch, axios와 같은 AJAX 통신 혹은 async/await 키워드처럼 Promise를 반환
할 수도 있다.자바스크립트 런타임의 이벤트 루프
를 이해해야 한다. / 자바스크립트 런타임은 Call Stack과 Memory Heap으로 구성된 자바스크립트 엔진과 Web API, Task Queue로 구성
된다. / 함수
가 호출되면 해당 함수는 Call Stack에 쌓이고 후입선출(LIFO, push&pop) 방식으로 처리
된다. 그러다가 비동기 함수
를 만나면 Call Stack에서 Web API에 위임
되고, Web API는 비동기 처리가 완료되면 비동기 함수의 콜백 함수를 Task Queue에 등록
한다. Task Queue에 등록된 콜백 함수들은 Call Stack이 비게 되면 그제서야 선입선출(FIFO, Enqueue&Dequeue) 방식으로 (Call Stack에서) 처리
된다.Microtask Queue
와 Macrotask Queue
로 구분할 수 있는데, Microtask Queue가 Macrotask Queue보다 높은 우선 순위
를 갖는다. / Microtask Queue에서는 Promise를 반환하는 fetch, axios, async/await 등
이 처리되고, Macrotask Queue에서는 XMLHttpRequest, 타이머 함수 등
이 처리된다.일정 시간 이후 혹은 일정 시간 간격으로 콜백 함수를 호출하는 비동기 함수
이다. 타이머 함수는 clearTimeout 혹은 clearInterval를 통해 종료시킬 수 있다.비동기 통신을 이용한 클라이언트와 서버 간의 데이터 교환 기술
이다. / 데이터를 주고 받을 때 새로고침이 발생하지 않
기 때문에 특정 부분만 렌더링하는 방식의 개발
이 가능해졌다.XMLHttpRequest
는 XML(요즘에는 JSON)과 HTTP 프로토콜을 이용하는 전통적인 데이터 교환 방식
이다. 이는 콜백 지옥
이 형성되어 가독성이 떨어진다는 단점이 있다. / 반면 fetch와 axios
는 Promise 기반
으로, then-catch 메서드 혹은 async/await의 try-catch문
를 통해 콜백 지옥
을 피할 수 있다. / 그러나 fetch는응답값을 json 메서드를 통해 JSON 포멧으로 변환주는 작업이 필요
하고, 네트워크 장애 상태만을 Rejected 상태
로 보기 때문에 에러 처리가 까다롭다. 이에 반해 axios는 응답값을 JSON 포멧으로 바로 제공하여 변환 작업이 필요없
고, 거의 모든 장애 상태를 Rejected 상태
로 보기 때문에 에러 처리도 수월하다.HTTP 통신을 위한 데이터 포멧
으로, 자바스크립트 객체
의 형태와 비슷하다. / 다만 key
를 쌍따옴표로 표현하고 value
에 특정 타입(함수, 정규표현식, undefined 등)은 사용할 수 없다는 차이가 있다.JSON 처리를 위한 표준 빌트인 객체인 JSON 객체
를 가지고 있다. JSON 객체에는 JSON.stringify
메서드와 JSON.parse
메서드가 있는데, JSON.stringify는 자바스크립트 객체를 JSON 문자열로 변환하는 직렬화 메서드
이고, JSON.parse는 JSON 문자열을 자바스크립트 객체로 변환하는 역직렬화 메서드
이다. / JSON.stringify는 요청을 보낼 때
, JSON.parse는 응답을 받을 때
많이 사용한다.함수의 매개변수로 들어오는 함수
로, 비동기 처리
를 위해 사용할 수 있다.비동기 처리를 위해 사용
되는, 내용은 실행되었지만 결과를 반환하지 않은 특수 객체
이다.
resolve, reject라는 콜백 함수를 가지는 함수
를 전달받아, 비동기 작업 성공 시 resolve, 실패 시 reject를 호출
한다. resolve가 실행
되면 Fullfilled State
가 되고 reject가 실행
되면 Rejected State
가 된다. Fullfilled State일 때는 then 메서드를 통해 결과를 반환
받을 수 있고, Rejected State일 때는 catch 메서드를 통해 결과를 반환
받을 수 있다.
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
if (success) {
resolve('작업이 완료되었습니다.');
} else {
reject('작업을 처리하는 중 오류가 발생했습니다.');
}
}, 1000);
});
myPromise.then((result) => {
console.log('성공:', result);
}).catch((error) => {
console.error('오류:', error);
});
비동기 함수를 만드는 키워드
로, async를 사용하면 함수가 항상 Promise를 반환하도록 하여 비동기적으로 동작하도록
만들고, await를 사용하면 해당 라인의 Promise가 결과를 반환할 때까지 대기시켜서 비동기 코드를 동기적으로 동작하도록
만든다. / 이를 활용하면 비동기 코드를 더 직관적으로 작성
할 수 있고 try-catch문을 통해 then 지옥을 해결
할 수 있다.function*
)코드 블록의 실행을 중지했다가 필요한 시점에 다시 실행하는 특수 객체
이다.
(제너레이터 함수를 호출
하면 함수가 바로 실행되지는 않고 제너레이터 객체를 반환
하는데, 이 객체의 next() 메서드
를 사용하면 제너레이터 함수를 실행
할 수 있다. 제네레이터 함수가 실행되면 다음 yield 키워드를 찾을 때까지 실행을 지속하고 (yield 뒤에 위치하는 값인) value를 반환
한다. `다음 yield가 없으면 ({ done: true }가 되면서) 제너레이터 함수는 종료되는데, 이 때 만약 return문이 있으면 반환값이 value가 된다.)
function* simpleGeneratorWithReturn() {
yield 1;
yield 2;
yield 3;
return 'Generator 실행 완료';
}
const generator = simpleGeneratorWithReturn();
console.log(generator.next().value); // 1
console.log(generator.next().value); // 2
console.log(generator.next().value); // 3
const result = generator.next();
if (result.done) {
console.log(result.value); // 'Generator 실행 완료'
}
특정 객체의 특정 작업을 가로채서 다른 작업을 수행하도록 하는 특수 객체
이다.
(두 개의 객체 파라미터를 가지는데, 첫 번째 파라미터에는 타겟 객체
이고, 두 번째 파라미터에는 핸들러 객체
이다. 핸들러 객체에는 내장 메서드의 동작을 가로채 어떠한 작업을 수행하는 트랩
을 정의한다. (get
, set
매서드를 사용하면 읽기/할당 동작을 가로챌 수 있다.))
const targetObject = {
name: 'DONGKYEONG',
age: 20
};
const handler = {
get: function (target, property) {
console.log(`속성을 읽는 중: ${property}`);
return target[property];
},
set: function (target, property, value) {
console.log(`속성을 설정하는 중: ${property} = ${value}`);
target[property] = value;
}
// get(){}, set(){} 형태도 OK
};
const proxy = new Proxy(targetObject, handler);
proxy.name; // "속성을 읽는 중: name", 결과: 'DONGKYEONG'
proxy.age = 30; // "속성을 설정하는 중: age = 30"
console.log(proxy.age); // "속성을 읽는 중: age", 결과: 30