🔖 자바스크립트 정리(1)(22.12.23 수정)
자바스크립트 탄생
- 1995년, 넷스케이프 커뮤니케이션즈에서 웹페이지의 보조적인 기능을 수행하기 위해 브라우저에서 동작하는 경량형 프로그래밍 언어를 도입하기로 결정하였는데 이것이 브래던 아이크가 개발한 자바스크립트이다.
크로스 브라우징 이슈
넷스케이프 커뮤니케이션즈와 마이크로소프트는 자사 브라우저의 점유율을 높이기 위해 자사 브라우저에서만 동작하는 기능을 경쟁적으로 추가하기 시작하였다.
브라우저에 따라 웹페이지가 정상적으로 동작하지 않는 크로스 브라우징 이슈가 발생하였다.
ECMAScript 등장
- 자바스크립트의 파편화를 방지하고 모든 브라우저에서 정상적으로 동작하는 표준화된 자바스크립트의 필요성이 느껴 1997년 7월에 ECMA-262라고 불리는 표준화된 자바스크립트 초판 사양이 완성되었고 상표권 문제로 ECMAScript로 명명되었다.
ES6 등장
- let/const 키워드
- 화살표 함수
- 템플릿 리터럴
- 디스트럭처링 할당
- 스프레드 문법
- rest 파라미터
- 심벌
- 프로미스
- Map/Set
- 이터러블
- for…of
- 제너레이터
- Proxy
- 모듈 import/export
렌더링
HTML, CSS, 자바스크립트로 작성된 문서를 해석하여 브라우저에 시각적으로 출력하는 것을 의미한다.
때로는 서버에서 데이터를 HTML로 변환해서 브라우저에게 전달하는 과정(SSR)을 가리키기도 한다.
AJAX
자바스크립트를 이용하여 서버와 브라우저가 비동기방식으로 데이터를 교환할 수 있는 통신기능을 의미한다.
Ajax의 등장으로 웹페이지에서 변경할 필요가 없는 부분은 다시 렌더링 하지않고, 서버로부터 필요한 데이터만 전송받아 변경해야 하는 부분만 한정적으로 렌더링하는 방식이 가능해졌다.
예시로 2005년 구글 맵스가 있다.
JQuery
- 2006년, DOM을 더욱 쉽게 제어할 수 있고 크로스 브라우징이슈도 어느정도 해결가능한 JQuery가 등장하였다.
Node.js
구글V8 자바스크립트 엔진으로 빌드된 자바스크립트 런타임 환경을 의미한다.
자바스크립트를 브라우저 이외의 환경에서 동작할 수 있도록 자바스크립트 엔진을 브라우저에서 독립시킨 자바스크립트 실행 환경이다.
서버 사이드 애플리케이션 개발에 주로 사용되며 이에 필요한 모듈, 파일 시스템, HTTP 등 빌트인 API를 제공한다.
프론트엔드와 백엔드 영역에서 자바스크립트를 사용할 수 있는 동형성을 가지고 있다.
비동기 I/O를 지원하고 단일 스레드 이벤트 루프 기반으로 동작하여 요청처리 성능이 좋다.
데이터를 실시간으로 처리하기 위해 I/O가 빈번하게 발생하는 SPA에 적합하다.
CPU 사용률이 높은 애플리케이션에는 권장하지 않는다.
npm(node packge manager)
- 노드 패키지 매니저는 자바스크립트 패키지 매니저이다.
- Node.js에서 사용할 수 있는 모듈들을 패키지화해서 모아둔 저장소 역할과 패키지 설치 및 관리를 위한 CLI를 제공한다.
SPA
최초 한번 페이지 전체를 로딩한 후, 데이터만 변경하여 사용할 수 있는 애플리케이션을 의미한다.
CSR이다.
자바스크립트 특징
- HTML, CSS와 함께 웹을 구성하는 요소중 하나로 웹브라우저에서 동작하는 유일한 프로그래밍 언어이다.
- 별도의 컴파일 작업을 수행하지 않는 인터프리터 언어이다.
- 명령형, 함수형, 프로토타입 기반 객체지향 프로그래밍을 지원하는 멀티 패러다임 프로그래밍 언어다.
- 프로토타입 기반의 객체지향 언어이다.
웹 크롤링
- 서버에서 웹사이트의 콘텐츠를 수집하기위해 웹사이트에서 HTML 문서를 가져온 다음, 이를 가공해서 필요한 데이터만 추출하는 것을 의미한다.
변수
- 값을 저장하기 위한 메모리공간의 이름을 의미한다.
- 값을 재사용하기 위하여 사용한다.
식별자
- 어떤 값을 구별해서 식별할 수 있는 고유한 이름을 의미한다.
- 변수를 식별자라고도 한다.
키워드
- 자바스크립트 코드를 해석하고 실행하는 자바스크립트 엔진이 수행할 동작을 규정한 일종의 명령어이다.
선언과 초기화
- 선언단계: 변수 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알린다.
- 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화한다.
호이스팅
- 모든 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트의 고유한 특징이다.
가비지 콜렉터
- 애플리케이션이 할당한 메모리공간을 주기적으로 검사하여 더이상 사용되지 않는 메모리를 해제하는 기능을 의미한다.
- 메모리 누수를 방지한다.
네이밍 컨벤션
하나 이상의 영어 단어로 구성된 식별자를 만들 때 가독성 좋게 단어를 한눈에 구분하기 위해 규정한 명명 규칙이다.
자바스크립트에서는 변수나 함수에 이름에는 카멜케이스를 사용하고 클래스의 이름, 생성자 함수는 파스칼 케이스를 사용한다.
예약어
- 프로그래밍 언어에서 사용되고 있거나 사용될 예정인 단어를 의미한다.
값
- 식이 평가되어 생성된 결과를 의미한다.
리터럴
- 사람이 이해할 수 있는 문자 또는 약속된 기호를 사용해 값을 생성하는 표기법을 의미한다.
표현식
값으로 평가될 수 있는 문이다.
표현식이 평가되면 새로운 값을 생성하거나 기존 값을 참조한다.
문
- 프로그램을 구성하는 기본 단위이자 최소 실행 단위다.
- 문은 여러 토큰으로 구성된다.
- 토큰: 문법적인 의미를 가지며 문법적으로 더이상 나눌 수 없는 코드의 기본 요소를 의미한다.
데이터 타입
- 자바스크립트는 7개의 데이터 타입을 가지고있다.
- 원시타입
- 숫자 타입: 정수와 실수 구분없이 모든 수를 실수처리하여 하나의 숫자타입이 존재한다.
- 문자열 타입: 문자열을 가진다.
- 불리언 타입: 논리적 참과 거짓을 가진다.
- undefined 타입: var 키워드로 선언된 변수에 암묵적으로 할당되는 값이다.
- null 타입: 값이 없다는 것을 의도적으로 명시할 때 사용하는 값이다.
- Symbol 타입: 다른 값과 중복되지 않는 유일무일한 값이다. 주로 이름 충돌할 위험이 없는 객체의 유일한 프로퍼티 키를 만들기 위해 사용한다.
- 객체타입
- 객체
- 함수
- 배열
- 원시타입
데이터 타입의 필요성
- 데이터 타입에 의한 메모리 공간의 확보와 참조
- 데이터 타입에 의한 값의 해석
- 값을 저장할때 확보해야하는 메모리 공간의 크기를 결정하기 위해
- 값을 참조할때 한번에 읽어 들여야할 메모리 공간의 크기를 결정하기 위해
- 메모리에서 읽어 들인 2진수를 어떻게 해석할지 결정하기 위해
동적 타이핑
- 자바스크립트의 변수는 선언이 아닌 할당에 의해 타입이 결정된다.(타입추론)
- 재할당에 의해 변수의 타입은 언제든 동적으로 변할 수 있다.
- 동적 타입 언어는 유연성은 높으나 신뢰성은 떨어진다.
동등/일치 비교연산자(==/===)
- 동등비교(==) 연산자는 좌항과 우항의 피연산자를 비교할 때 먼저 암묵적으로 타입 변환을 통해 타입을 일치 시긴 후 같은 값인지 비교한다.
- 일치비교(===) 연산자는 암묵적 타입변환을 하지않고 값을 비교한다.
- typeof 연산자는 일치비교연산자와 동일하게 동작하지만, null은 object로 반환되는 버그가 존재하기 때문에 일치연산자를 사용하는 것을 권장한다.
타입 변환
- 명시적 타입 변환(타입 캐스팅): 개발자가 의도적으로 값의 타입을 변환 하는 것
암묵적 타입 변환(타입 강제 변환): 개발자의 의도와 상관없이 평가하는 도중에 자바스크립트 엔진에 의해 암묵적으로 타입이 변환 되는 것
- 타입 변환은 기존 원시 값을 직접 변경하지 않고 다른 타입의 새로운 원시 값을 생성하는 것이다.
단축 평가
- 표현식이 평가하는 도중 평가 결과가 확정된 경우 나머지 평가 과정을 생략하는 것을 의미한다.
- 단축평가의 활용
- 객체를 가리키기 기대하는 변수가 null 또는 undefined가 아닌지 확인하고 프로퍼티를 참조할 때
- 함수 매개변수에 기본값을 설정할 때
옵셔널 체이닝 연산자(?.
)
- ES11에서 도입되었다.
- 좌항의 피연산자가 null 또는 undefined인 경우 undefined를 반환하고 그렇지 않으면 우항의 프로퍼티 참조를 이어가는 것을 의미한다.
- 객체를 가리키기를 기대하는 변수가 null 또는 undefined가 아닌지 확인하고 프로퍼티를 참조할 때 유용하다.
null 병합 연산자 (??
)
- ES11에서 도입되었다.
- 좌항의 피연산자가 null 또는 undefined일 경우 우항의 피연산자를 반환하고 그렇지 않으면 좌항의 피연산자를 반환한다.
- 변수에 기본값을 설정할때 유용하다.
객체
- 자바스크립트는 객체 기반의 프로그래밍 언어이며 자바스크립트를 구성하는 거의 모든 것이 객체다.
- 원시 값을 제외한 나머지 값들은 모두 객체다.
- 객체 타입은 다양한 타입의 값을 하나의 단위로 구성한 복합적인 자료구조이다.
- 객체는 변경 가능한 값이다.
- 0개 이상의 프로퍼티로 구성된 집합이며 프로퍼티는 키와 값으로 구성된다.
- 프로퍼티: 객체의 상태를 나타내는 값
- 메서드: 프로퍼티를 참조하고 조작할 수 있는 동작
- 상태와 동작을 하나의 단위로 구조화 할 수 있어 유용하다.
인스턴스
클래스에 의해 생성되어 메모리에 저장된 실체를 의미한다.
객체 = 클래스 + 인스턴스
객체 생성 방법
- 객체 리터럴
- 가장 일반적이고 간단한 방법
- 프로퍼티를 동적으로 추가할 수 있다.
- Object 생성자 함수
- 생성자 함수
- Object.create 메서드
- 클래스(ES6)
프로퍼티
객체는 프로퍼티의 집합이며, 프로퍼티는 키와 값으로 구성된다.
- 프로퍼티 키: 빈 문자열을 포함하는 모든 문자열 또는 심벌 값
- 프로퍼티 값: 자바스크립트에서 사용할 수 있는 모든 값
메서드
- 프로퍼티의 값이 함수일 경우 일반 함수와 구분하기 위해서 지칭하는 것이다.
프로퍼티 접근(마침표 표기법과 대괄호 표기법)
- 마침표 표기법:
.
- 대괄호 표기법:
[...]
- 프로퍼티 키는 반드시 따옴표로 감싼 문자열이어야 된다.
- 객체에 존재하지 않는 프로퍼티에 접근하면 undefined를 반환한다.
원시 값과 객체의 비교
- 원시값
- 원시 값은 변경 불가능한 값이다.
- 원시 값을 변수에 할당하면 변수에는 실제 값이 저장된다.
- 원시 값을 다른 변수에 할당하면 원본의 원시 값이 복사되어 전달한다. (값에 의한 전달/pass by value)
- 원시값은 불변성(immutability)이다.
- 객체
- 객체는 변경 가능한 값이다.
- 객체를 변수에 할당하면 변수에는 참조 값이 저장된다.
- 객체를 다른 변수에 할당하면 원본의 참조 값이 복사되어 전달한다. (참조에 의한 전달/pass by reference)
자바스크립트 객체의 관리 방식
- 프로퍼티 키를 인덱스로 사용하는 해시 테이블(연관 배열, map)이라고 생각하면 된다.
- V8 자바스크립트 엔진에서는 프로퍼티에 접근하기 위해 동적탐색 대신 히든 클래스 방식을 사용해 C++객체의 프로퍼티에 접근하는 정도의 성능을 보장한다.
얕은 복사와 깊은 복사
- 얕은 복사: 한 단계 까지만 복사하는 것을 의미한다.
- 객체에 중첩되어 있는 객체의 경우 참조 값을 복사한다.
- 객체에 할당한 변수를 다른 변수에 할당하는 경우를 의미한다.
- 스프레드 문법으로도 얕은 복사가 가능하다.
- 깊은 복사: 객체에 중첩되어있는 객체까지 모두 복사하는 것을 의미한다.
- 객체에 중첩되어 있는 객체의 경우 중첩되어 있는 객체까지 모두 복사해서 원시 값처럼 완전한 복사본을 만든다.
- 원시 값을 할당한 변수를 다른 변수에 할당하는 경우를 의미한다.
- Nods.js의 lodash으로도 깊은 복사가 가능하다.
함수
- 일련의 과정을 문으로 구현하고 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것이다.
- 매개변수: 함수 내부로 입력을 전달받는 변수
- 인수: 입력
- 반환값: 출력
- 함수는 객체이다.
- 일반 객체는 호출할 수 없지만 함수는 호출할 수 있다.
- 함수는 한가지 일만 해야하며 가급적 작게 만들어야 한다.
함수를 사용하는 이유
- 코드의 재사용에서 매우 유용하기 때문이다.
- 유지보수의 편의성을 높이고 실수를 줄여 코드의 신뢰성을 높힌다.
- 코드의 가독성을 향상시킨다.
함수 정의
- 함수 선언문
- 표현식이 아닌 문이기 때문에 함수 이름을 생략할 수 없다.
- 자바스크립트 엔진은 생성된 함수를 호출하기 위해 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고, 거기에 함수 객체를 할당한다.
- 함수 이름으로 호출하는 것이 아니라 함수 객체를 가리키는 식별자로 호출한다.
- 함수 호이스팅이 발생한다.
- 함수 표현식
- 표현식인 문이기 때문에 함수 이름을 생략 가능하다.
- 변수 호이스팅이 발생한다.
- Function 생성자 함수
- 클로저를 생성하지 않고 함수 선언문이나 표현식으로 생성한 함수와 다르게 동작한다.
- 화살표 함수
- 항상 익명함수로 정의한다.
- 표현과 내부 동작이 간략화되어 있다.
- this 바인딩이 다르다.
- prototype 프로퍼티가 없고 arguments 객체를 생성하지 않는다.
즉시 실행 함수(IIFE)
- 함수 정의와 동시에 즉시 호출되는 함수를 의미한다.
- 단 한번만 호출되며 다시 호출할 수 없다.
- 변수에 할당하여 인수를 전달할 수 있다.
1
2
3
4
5
(function () {
var a = 1;
var b = 2;
return a * b;
}());
재귀 함수
- 함수가 자기 자신을 호출하여 작동하는 함수를 의미한다.
- 재귀 함수를 사용하여 반복되는 처리를 반복문 없이 구현할 수 있다.
- 탈출 조건이 반드시 필요하다.
- 탈출 조건이 없으면 함수가 무한 호출되어 스택 오버플로 에러가 발생한다.
1
2
3
4
5
6
function countdown(n) {
if (n < 0) return;
console.log(n)
countdown(n - 1)
}
countdown(10)
중첩 함수(내부 함수)
- 함수 내부에 정의된 함수를 의미한다.
외부 함수: 중첩함수를 포함하는 함수를 의미한다.
- 중첩 함수는 외부 함수 내부에서만 호출이 가능하다.
- 중첩 함수는 외부 함수를 돕는 헬퍼 함수의 역할을 한다.
콜백 함수
- 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수를 의미한다.
- 함수형 프로그래밍 패러다임과 비동기처리(이벤트 처리, Ajax 통신, 타이머 함수)에 활용된다.
- 고차 함수: 매개 변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수를 의미한다.
- 콜백 함수를 자신의 일부분으로 합성한다.
- 매개변수를 통해 전달받은 콜백 함수의 호출 시점을 결정해 호출한다.
- 콜백함수는 고차 함수에 의해 호출되며 고차함수는 필요에 따라 콜백함수에 인수를 전달할 수있다.
부수 효과(Side Effect)
- 어떤 외부 상태에 의존하여 외부 상태를 변경되는 것을 의미한다.
순수 함수와 비순수 함수
- 순수 함수: 부수효과가 없는 함수를 의미한다.
- 동일한 인수가 전달되면 언제나 동일한 값을 반환한다.
- 매개변수가 있는 것
- 비순수 함수: 부수효과가 있는 함수를 의미한다.
- 매개변수가 없어도 외부상태가 변하는 것
함수형 프로그래밍
- 순수 함수를 통해 부수 효과를 최대한 억제하여 오류를 피하고, 프로그램의 안정성을 높이려는 프로그래밍 패러다임을 의미한다.
- 순수 함수와 보조함수의 조합을 통해 로직 내 존재하는 조건문과 반복문을 제거하여 복잡성을 해결하고 변수의 사용을 억제하여 상태 변경을 피하려는 프로그래밍 패러다임이다.
스코프(유효범위)
식별자가 자신이 선언된 위치에 의해 다른 코드가 식별자 자신을 참조할 수 있는 유효 범위를 결정하는 것을 의미한다.
식별자가 유효한 범위를 의미한다.
식별자를 검색할 때 사용하는 규칙을 의미한다.
스코프는 네임스페이스다.
스코프 체인
- 스코프가 계층적으로 연결된 것을 의미한다.
- 변수를 참조할 때 자바스크립트 엔진은 스코프 체인을 통해 변수를 참조하는 코드의 스코프에서 시작하여 상위 스코프 방향으로 이동하여 선언된 변수를 검색한다.
- 식별자 검색을 위한 메커니즘이라고 할 수 있다.
함수 레벨 스코프
- var 키워드로 선언된 변수는 함수의 코드 블록만을 지역 스코프로 인정한다.
블록 레벨 스코프
- let, const 키워드로 선언된 변수는 블록을 지역스코프로 인정한다.
렉시컬 스코프(정적 스코프)
- 함수를 어디서 정의하는지에 따라 상위 스코프를 결정한다.
- 함수의 상위 스코프는 언제나 자신이 정의된 스코프다.
- 함수 정의가 실행되어 생성된 객체는 결정된 상위 스코프를 기억한다.
- 함수가 호출될 때마다 함수의 상위스코프를 참조할 필요가 있기 때문이다.
- 상위 스코프에 대한 참조는 함수 정의가 평가되는 시점에 함수가 정의된 환경(위치)에 의해 결정된다.
전역 객체
- 코드가 실행되기 이전 단계에 자바스크립트 엔진에 의해 어떤 객체보다도 먼저 생성되는 특수한 객체를 의미한다.
- 표준 빌트인 객체와 호스트객체, 전역변수와 전역 함수를 프로퍼티로 갖는다.
지역 변수
- 지역 변수의 생명 주기는 함수의 생명 주기와 일치한다.
- 스코프를 참조하고 있으면 스코프는 소멸하지 않고 생존하게 된다.
전역 변수
단점
- 모든 코드가 전역 변수를 참조하고 변경할 수 있는 암묵적 결합을 허용하는 것이 단점이다.
- 변수의 유효 범위가 크면 클수록 코드의 가독성이 나빠지고 의도치 않게 상태가 변경될 수 있는 위험도 있다.
- 긴 생명 주기
- 스코프 체인 상에서 종점에 존재
- 전역 변수의 검색 속도가 가장 느리다.
- 네임스페이스 오염
- 파일이 분리되어 있어도 하나의 전역 스코프를 공유한다.
- 모든 코드가 전역 변수를 참조하고 변경할 수 있는 암묵적 결합을 허용하는 것이 단점이다.
전역 변수 사용의 억제
변수의 스코프는 좁을수록 좋다
즉시 실행 함수(라이브러리 등에 자주 사용)
네임스페이스 객체(식별자 충돌 방지는 효과가 있으나 결국 전역 변수에 할당되는 것이다.)
모듈 패턴
- 클래스를 모방해서 관련이 있는 변수와 함수를 모아 즉시 실행 함수로 감싸 하나의 모듈을 만드는 것이다.
- 전역 변수의 억제와 캡슐화 구현이 가능하다는 특징이 있다.
ES6 모듈
전역 변수를 사용할 수 없게 된다.
파일 자체의 독자적인 모듈 스코프를 제공한다.
1
<script type="module" src="app.mjs"></script>
- 트랜스파일링이나 번들링이 필요하기 때문에 ES6 모듈보다 모듈 번들러를 사용하는 것이 일반적이다.
캡슐화
- 프로퍼티와 메서드를 하나로 묶는 것을 의미한다.
- 객체의 상태를 나타내는 프로퍼티와 프로퍼티를 참조하고 조작할 수 있는 동작인 메서드를 하나로 묶는 것을 말한다.
- 정보은닉을 위해 사용한다.
- 정보은닉: 객체의 특정 프로퍼티나 메서드를 감출 목적으로 사용하는 것이다.
- 외부에 공개할 필요가 없는 구현의 일부를 외부에 공개되지 않도록 감추어 적철지 못한 접근으로 부터 객체의 상태가 변경되는 것을 방지해 정보를 보호하고, 결합도를 낮추는 효과가 있다.
- 결합도: 객체간의 상호 의존성을 의미한다.
var 키워드 문제점
- 변수 중복 선언 허용
- 의도치 않게 선언된 변수 값을 변경할 수 있는 부작용
- 함수 레벨 스코프
- 전역 변수를 남발할 가능성이 높음
- 변수 호이스팅
- 선언과 초기화가 동시에 진행된다.
- 가독성을 떨어뜨리고 오류를 발생시킬 여지가 있음
let 키워드
- 변수 중복 선언 허용
- 블록 레벨 스코프
- 변수 호이스팅
- 선언과 초기화가 분리되어 진행된다.
- 스코프의 시작 시점부터 초기화 시작 지점까지 변수를 참조할 수 없는 구간을 일시적사각지대(Temporal Dead Zone:TDZ)라고 한다.
const 키워드
- 상수를 선언하기 위해 사용한다.
- 선언과 초기화
- 반드시 선언과 동시에 초기화 해야한다.
- 재할당 금지
- 상수
- 재할당이 금지된 변수를 의미한다.
- 상태 유지와 가독성, 유지보수에 도움이 된다.
- 상수의 이름은 대문자로 선언해 상수임을 명확하게 나타내며 여러단어로 이루어질 경우 언더코어로 구분해서 스네이크 케이스로 표현한다.
- const 키워드와 객체
- 객체를 할당한 경우 값을 변경할 수 있다.
내부슬롯과 내부 메서드
- 자바스크립트 엔진의 구현 알고리즘을 설명하기 위해 ECMAScript 사양에서 사용하는 의사 프로퍼티, 의사 메서드이다.
- 개발자가 직접 접근할 수 있도록 외부에 공개된 프로퍼티는 아니다. 하지만 일부 내부 슬롯과 내부 메서드에 한하여 간접적으로 접근할 수 있는 수단을 제공하기는 한다.
- 모든 객체는 [[Prototype]] 이라는 내부 슬롯을 갖는다.
__proto__
를 통해 간접적으로 접근할 수 있다.
프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체
자바스크립트 엔진은 프로퍼티를 생성할 때 프로퍼티의 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 자동 정의한다.
- 프로퍼티 상태: 프로퍼티 값, 값 갱신가능 여부, 열거 가능 여부, 재정의 가능 여부
- Obeject.getOwnPropertyDescriptor 메서드를 사용하여 간접적으로 프로퍼티 어트리뷰트를 확인 가능하다.
- Obeject.getOwnPropertyDescriptors 메서드를 사용하여 모든 프로퍼티의 프로퍼티 어트리뷰트정보를 제공하는 프로퍼티 디스크립터 객체들을 반환한다.
데이터 프로퍼티와 접근자 프로퍼티
- 데이터 프로퍼티: 키와 값으로 구성된 일반적인 프로퍼티
- 데이터 프로퍼티 어트리뷰트: [[Value]], [[Writable]], [[Enumerable]], [[Configurable]]
- 접근자 프로퍼티: 자체적으로 값을 가지고 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 호출되는 접근하 함수로 구성된 프로퍼티
- 접근자 프로퍼티 어트리뷰트: [[Get]], [[Set]], [[Enumerable]], [[Configurable]]
프로퍼티 정의
- 새로운 프로퍼티를 추가하면서 프로퍼티 어트리뷰트를 명시적으로 정의하거나 기존 프로퍼티의 프로퍼티 어트리뷰트를 재정의 하는 것을 의미한다.
- Object.defineProperty 메서드로 한번에 하나의 프로퍼티의 어트리뷰트를 정의할 수 있다.
- Object.defineProperties 메서드로 여러 개의 프로퍼티를 한 번에 정의할 수 있다.
객체 변경 방지 메서드
- Object.preventExtensions: 삭제, 읽기, 쓰기, 재정의 가능(확장 금지)
- Object.isExtensible: 확장이 가능한 객체인지 여부를 알 수 있는 메서드
- Object.seal: 읽기, 쓰기 가능(밀봉)
- Object.isSealed: 밀봉된 객체인지 확인하는 메서드
- Object.freeze: 읽기만 가능(동결)
- Object.isFrozen: 동결된 객체인지 확인하는 메서드
얕은 변경 방지로 직속 프로퍼티만 변경이 방지되고 중첩 객체까지는 영향을 주지 못한다.
불변 객체를 구현하려면 재귀적으로 사용해야한다.
생성자 함수
new 연산자와 함께 호출하여 객체(인스턴스)를 생성하는 함수를 의미한다.
- 인스턴스(instance): 생성자 함수에 의해 생성된 객체를 의미한다.
- 역할: 프로퍼티 구조가 동일한 인스턴스를 생성하기 위한 템플릿(클래스)으로서 동작하여 인스턴스를 생성하는 것과 생성된 인스턴스를 초기화(인스턴스 프로퍼티 추가 및 초기값 할당)하는 것
- 생성자 함수가 인스턴스를 생성하는 것은 필수이며, 생성된 인스턴스를 초기화 하는것은 옵션이다.
- 인스턴스 생성과정
- 인스턴스 생성과 this 바인딩
- 인스턴스 초기화
- 인스턴스 반환
- return문은 반드시 생략해야 한다.
바인딩
- 식별자와 값을 연결하는 과정을 의미한다.
내부 메서드 [[Call]]과 [[Construct]]
- 함수가 일반 함수로서 호출되면 함수 객체의 내부 메서드 [[Call]]이 호출되고, new 연산자와 함께 생성자 함수로서 호출되면 내부 메서드 [[Construct]]가 호출된다.
- callable: 내부 메서드 [[Call]]을 갖는 함수 객체
- 즉, 함수를 의미한다.
- constructor: 내부 메서드 [[Construct]]를 갖는 함수 객체, 생성자 함수로서 호출할 수 있는 함수를 의미한다.
- 예시) 함수 선언문, 함수 표현식, 클래스
- non-constructor: 객체를 생성자 함수로서 호출할 수 없는 함수를 의미한다.
- 예시) 메서드(ES6 메서드 축약 표현), 화살표 함수
모든 함수는 호출할 수 있지만, 모든 함수 객체를 생성자 함수로서 호출할 수 있는 것은 아니다.
new.target(메타 프로퍼티)
- 생성자 함수가 new 연산자 없이 호출되는 것을 방지하기 위해 파스칼 케이스 컨벤션을 사용한다 하더라도 실수는 언제나 발생할 수 있다.
- 이런 위험성을 회피하기 위해 ES6에서 new.target을 지원한다.
- new 연산자와 함께 생성자 함수로서 호출되면 함수 내부의 new.target은 함수 자신을 가르킨다.
- new 연산자 없이 일반 함수로서 호출된 함수 내부의 new.target은 unedfined다.
일급 객체
- 무명의 리터럴로 생성할 수 있다.
- 변수나 자료구조에 저장할 수 있다.
- 함수의 매개변수에 전달할 수 있다.
- 함수의 반환값으로 사용할 수 있다.
이 조건에 만족하는 객체를 일급 객체라고 하며 자바스크립트에서는 함수도 일급 객체이다.
함수 객체의 프로퍼티
- arguments: 함수 호출 시 인수들의 정보를 담고 있는 순회 가능한(iterable) 유사 배열 객체이며, 함수 내부에서 지역 변수처럼 사용된다.
- 매개변수 개수를 확정할 수 없는 가변 인자 함수를 구현할 때 유용하다.
caller: ECMAScript 사양에 포함되지 않은 비표준 프로퍼티이며, 함수 자신을 호출한 함수이다.
- length: 함수를 정의할 때 선언한 매개변수의 개수이다.
- arguments 객체의 length 프로퍼티는 인수의 개수, 함수 객체의 length 프로퍼티는 매개변수의 개수를 가리킨다.
name: 함수의 이름을 나타낸다.
- prototype: 생성자 함수로 호출할 수 있는 함수 객체, 즉 constructor만이 소유하는 프로퍼티이다.
자바스크립트
- 명령형, 함수형, 프로토타입 기반 객체 지향 프로그래밍을 지원하는 멀티 패러다임 프로그래밍 언어이다.
객체 지향 프로그래밍
- 여러 개의 독립 적 단위인 객체를 집합으로 프로그램을 표현하려는 프로그래밍 패러다임을 의미한다.
- 실세계의 실체를 인식하는 철학적사고를 프로그래밍에 접목하려는 시도에서 시작된다.
객체
- 상태와 동작을 하나의 논리적인 단위로 묶은 복합적인 자료구조이다.
- 프로퍼티와 메서드로 구성되어 있다.
추상화
- 다양한 속성 중에서 프로그램에 필요한 속성만 간추려 내는 것
상속
- 어떤 객체의 프로퍼티 또는 메서드를 다른 객체가 상속받아 그대로 사용할 수 있는 것을 의미한다.
- 자바스크립트는 프로토타입을 기반으로 상속을 구현하여 불필요한 중복을 제거한다.
프로토타입 객체
- 객체지향 프로그래밍의 근간을 이루는 객체 간 상속을 구한하기위해 사용되는 것이다.
- 프로토타입은 어떤 객체의 상위 객체의 역할을 하는 객체이다. 다른 객체에 공유 프로퍼티를 제공한다.
__proto__
접근자 프로퍼티
모든 객체는
__proto__
접근자 프로퍼티를 통해 자신의 프로퍼티 즉, [[Prototype]] 내부 슬롯에 간접적으로 접근할 수 있다.__proto__
는 상속을 통해 사용된다.- 하지만 코드 내에서
__proto__
접근자 프로퍼티를 직접 사용하는 것은 권장하지 않는다.- 모든 객체가
__proto__
접근자 프로퍼티를 사용하는 것은 아니기 때문이다. - 예를 들어 직접 상속을 받았을 때를 말한다.
- 때문에, 프로토타입의 교체를 하고 싶을 경우 Object.getPrototypeOf 메서드와 Object.setPrototypeOf 메서드를 사용하는 것을 권장한다.
- 모든 객체가
__proto__
를 통해 프로토타입에 접근하는 이유
- 상호 참조에 의해 프로토타입 체인이 생성되는 것을 방지하기 위해 사용한다.
- 프로토타입 체인은 단뱡향 링크드 리스트로 구현해야한다.
- 검색방향이 한쪽으로 흘러가는 것을 의미한다.
함수 객체의 prototype 메서드
- 함수 객체만이 소유하는 prototype 프로퍼티는 생성자 함수가 생성할 인스턴스의 프로토타입을 가리킨다.
객체 리터럴과 object 생성자 함수의 차이
- 추상 연산 OrdinaryObjectCreate를 호출하여 빈 객체를 생성하는 것은 동일하다.
- new.target의 확인이나 프로퍼티를 추가하는 처리 등 세부 내용이 다르다.
프로토타입의 생성 시점
- 생성자 함수가 실행되는 시점에 생성된다.
- 프로토타입과 생성자 함수는 단독으로 존재할 수 없고 언제나 쌍으로 존재하기 때문이다.
프로토타입 체인
- 프로토타입 체인: 자바스크립트는 객체의 프로퍼티에 접근하려고 할 때, 해당 객체에 접근하려는 프로퍼티가 없다면 [[Prototype]] 내부 슬롯의 참조를 따라 자신의 부모 역할을 하는 프로토타입의 프로퍼티를 순차적으로 검색한다.
- 자바스크립트가 객체 지향 프로그래밍의 상속을 구현하는 메커니즘이다.
프로토타입 체인은 상속과 프로퍼티 검색을 위한 메커니즘이라고 할 수 있다.
- 스코프 체인과 프로토타입 체인은 서로 협력하여 식별자와 프로퍼티를 검색하는데 사용된다.
프로퍼티 섀도잉
- 상속관계에 의해 프로퍼티가 가려지는 현상을 의미한다.
오버라이딩
- 상위 클래스가 가지고 있는 메서드를 하위 클래스가 재정의 하여 사용하는 방식이다.
오버로딩
- 함수의 이름은 동일하지만 매개변수의 타입 또는 개수가 다른 메서드를 구현하고 매개변수에 의해 메서드를 구별하여 호출하는 방식이다.
- 자바스크립트는 오버로딩을 지원하지 않지만, arguments 객체를 사용하여 구현할 수 있다.
instance of 연산자
- 우변의 생성자 함수의 prototype에 바인딩된 객체가 좌변의 객체의 프로토타입 체인 상에 존재하면 true를 반환하고, 그렇지 않는 경우에는 false로 반환한다.
Object.create에 의한 직접 상속
- Object.create 메서드는 명시적으로 프로토타입을 지정하여 새로운 객체를 만든다.
- 장점
- new 연산자 없이도 객체 생성 가능
- 프로토타입을 지정하면서 객체 생성가능
- 객체 리터럴에 의해 생성된 객체도 상속받을 수 있음
- ESLint에서 이 방식을 권장하지 않음
- 프로토타입 체인의 종점에 위치하는 객체는 Object.prototype의 빌트인 메서드를 사용할 수 없기 때문이다.
정적 프로퍼티와 정적 메서드
- 정적프로퍼티와 정적 메서드는 생성자 함수로 인스턴스를 생성하지 않아도 참조하거나 호출할 수 있는 프로퍼티와 메서드를 의미한다.
- 만약 인스턴스/프토토타입 메서드 내에서 this를 사용하지 않는다면 그 메서드는 정적 메서드로 변경할 수 있다.
in 연산자 - 프로퍼티 존재 확인
객체 내에 특정 프로퍼티가 존재하는지 여부를 확인한다.
확인 대상 객체의 프로퍼티뿐만 아니라 확인 대상 객체가 상속받은 프로토타입의 프로퍼티까지 확인하여 주의가 필요하다.
Object.prototype.hasOwnPropery 메서드 - 프로퍼티 존재 확인
- 객체에 특정 프로퍼티가 존재하는지 확인 가능하다.
for … in 문 - 프로퍼티 열거
- 객체의 프로토타입 체인 상에 존재하는 모든 프로토타입의 프로퍼티 중에서 프로퍼티 어트리뷰트 [[Enumerable]] 값이 true인 프로퍼티를 순회하여 열거한다.
- 순서를 보장하지 않는다.
- 대부분 모던 브라우저는 순서를 보장하고 숫자인 프로퍼티 키에 대해서는 정렬을 실시한다.
Object.keys/values/entries 메서드 - 프로퍼티 열거
- 객체 자신의 고유 프로퍼티만 열거하기 위한 메서드이다.
- 열거 가능한 프로퍼티
키
/값
/키와 값의 쌍의 배열
을 배열로 반환한다.
strict mode(엄격 모드)
엄격 모드를 사용하면 자바스크립트 언어의 문법을 좀 더 엄격히 적용하여 오류를 발생시키거나 자바스크립트 엔진의 최적화 문제를 일으킬 수 있는 코드에 대해 명시적인 에러를 발생시킨다.
- ES6의 클래스와 모듈은 strict mode가 기본적으로 적용된다.
- 코드 선두에
'use strict';
를 추가하면 적용된다.- 전역에 사용하는 것, 함수 단위로 적용하는 것은 권장하지 않는다.
ESLint
- strict mode와 유사한 효과를 얻을 수 있는 도구이다.
- 정적 분석을 통해 소스코드를 실행하기전에 소스코드를 스캔하여 문법적인 오류와 잠재적 오류를 찾아내고 오류의 원인을 리포팅 해주는 도구이다.
strict mode가 발생시키는 에러
- 암묵적 전역
변수, 함수, 매개변수의 삭제
- 매개변수 이름의 중복
- with 문의 사용
strict mode 적용에 의한 변화
- 일반함수 this
- undefined가 반환됨
- arguments 객체
- 매개변수에 전달된 인수를 재할당하여 변경하여도 arguments 객체에 반영되지 않음
빌트인 객체
- 표준 빌트인 객체
- ECMAScript 사양에 정의된 객체이며 애플리케이션 전역의 공통 기능을 제공한다. 전역 객체의 프로퍼티로서 제공되어 별도의 선언 없이 전역변수처럼 언제나 참조할 수 있다.
- 호스트 객체
- ECMAScript 사양에 정의되어 있지 않지만, 자바스크립트 실행 환경에서 추가로 제공하는 객체이다.
- 브라우저 환경: 클라이언트 사이드 Web API 제공
- 사용자 정의 객체
- 사용자가 직접 정의한 객체를 의미한다.
래퍼 객체(wrapper object)
- 문자열, 숫자, 불리언 값에 대해 객체처럼 접근하면 생성되는 임시 객체를 의미한다.
URI(Uniform Resource Identifier)
- 인터넷에 있는 자원을 타나내는 유일한 주소를 의미한다.
URL(Uniform Resource Locator)
- 인터넷에서 웹 페이지, 이미지, 비디오 등 리소스의 위치를 가리키는 문자열을 의미한다.
URN(Uniform Resource Name)
- 이름으로 리소스를 특정하는 URI를 의미한다.
암묵적 전역
- var, let, const 키워드 없이 변수를 선언한 경우, 자바스크립트 엔진은 암묵적으로 전역 객체에 프로퍼티를 동적 생성되어 해당 변수를 마치 전역 변수처럼 사용할 수 있는 것을 의미한다.
this
자신이 속한 객체나 자신이 생성할 인스턴스를 가리키는 자기 참조 변수를 의미한다.
함수가 호출되는 방식에 따라 this 바인딩이 동적으로 결정된다.
함수 호출 방식에 따른 this
- 일반함수에서 호출(중첩 함수, 콜백 함수)
- 전역 객체를 가르킨다.
- 메서드에서 호출
- 메서드를 호출하는 객체를 가르킨다.
- 생성자 함수에서 호출
- 생성자 함수에서 생성될 인스턴스를 가르킨다.
apply
/call
/bind
메서드에 의한 간접 호출- apply: this를 원하는 것으로 지정 가능하다. 두번째 인자 형식은 배열로 묶어 전달한다.
- call: this를 원하는 것으로 지정 가능하다. 두번째 인자 형식은 리스트 형식으로 묶어 전달한다.
- bind: this를 영구적으로 원하는 것으로 지정 가능하다.
apply / call 공통점과 차이점
공통점: 대표적인 용도는 arguments 객체와 유사 배열 객체에 배열 메서드를 사용하는 경우에 쓴다. 비동기 코드에 유리하다.
차이점: 인자의 형식이 다르다.
apply, call / bind 공통점과 차이점
공통점: apply, call, bind는 Function.prototype의 메서드이므로 모든 함수가 상속받아 사용 가능하다.
차이점
bind는 apply와 call 메서드와 달리 함수를 호출하지 않고 this로 사용할 객체만 전달한다
bind 메서드는 메서드의 this와 메서드 내부의 중첩함수 또는 콜백함수의 this가 불일치하는 문제를 해결하기 위해 유용하게 사용한다.
- 일반함수에서 호출(중첩 함수, 콜백 함수)
실행 컨텍스트
자바스크립트의 동작 원리를 담고 있는 핵심 개념이다.
소스코드를 실행하는데 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역이다.
- 식별자를 등록하고 관리하는 스코프와 코드 실행 순서 관리를 구현한 내부 메커니즘으로, 모든 코드는 실행 컨텍스트를 통해 실행되고 관리된다.
실행 컨텍스트 스택
- 실행 컨텍스트를 스택 자료구조로 관리하는 것을 의미한다.
- 코드의 실행 순서를 관리하는 것이다.
- 실행 컨텍스트의 최상위에 존재하는 실행 컨텍스트는 실행 중인 실행 컨텍스트이다.
렉시컬 환경
- 식별자와 식별자에 바인딩된 값, 상위 스코프에 대한 참조를 기록하는 자료구조로 실행 컨텍스트를 구성하는 컴포넌트이다.
- 스코프를 구분하여 식별자를 등록하고 관리하는 저장소의 역할을 하는 것이다.
클로저
함수와 그 함수가 선언된 렉시컬 환경과의 조합이다.
외부함수보다 중첩함수가 더 오래 유지되는 경우, 중첩함수는 이미 생명주기가 다한 외부함수의 변수를 참조할 수 있다. 이러한 중첩함수를 클로저라고 한다.
클로저는 중첩 함수가 상위스코프의 식별자를 참조하고 있고 중첩함수가 외부 함수보다 더 오래 유지되는 경우에 한정하는 것이 일반적이다.
1 2 3 4 5 6 7 8 9 10 11 12 13
const x = 1; function outerFunc() { const x = 10; function innerFunc() { console.log(x); // 10 } innerFunc() } outerFunc();
자유변수: 클로저에 의해 참조되는 상위 스코프의 변수를 의미한다.
클로저는 자유 변수에 묶여있는 함수라고 할 수 있다.
클로저의 활용
상태를 안전하게 변경하고 유지하기 위해 사용한다. (정보 은닉)
특정함수에게만 상태 변경을 허용하기 위해 사용한다.
즉시 실행 함수 활용하여 return을 함수로 반환
즉, 클로저는 상태가 의도치 않게 변경되지 않도록 안전하게 은닉하고 특정 함수에게만 상태 변경을 허용하여 상태를 안전하게 변경하고 유지하기 위해 사용한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
const counter = (function() { let counter = 0; return function (predicate) { counter = predicate(counter); return counter; } }()); function increase(n) { return ++n; } function decrease(n) { return --n; } console.log(counter(increase)) // 1 console.log(counter(increase)) // 2 console.log(counter(decrease)) // 1 console.log(counter(decrease)) // 0
클래스
- 클래스도 함수이며 기존 프로토타입 기반 패턴을 클래스 기반 패턴처럼 사용할 수 있도록 하는 문법적 설탕이다.
- 클래스를 프로토타입 기반 객체 생성 패턴의 단순한 문법적인 설탕보다 새로운 객체 생성 메커니즘이라고 할 수 있다.
클래스와 생성자 함수의 차이
- 공통점
- 인스턴스를 생성한다.
- 프로토타입 기반의 객체지향을 구현한다는 점에서 유사하다.
- 차이점
- 클래스를 new 연산자 없이 호출하면 에러가 발생한다. 하지만 생성자 함수는 new 연산자 없이 호출하면 일반 함수로 호출된다.
- 클래스는 상속을 지원하는 extends와 super 키워드를 제공한다. 하지만 생성자 함수는 이 키워드를 제공하지 않는다.
- 클래스는 호이스팅이 발생하지 않는 것처럼 동작한다. 하지만 함수 선언문으로 정의된 생성자 함수는 함수 호이스팅이 발생하고, 함수 표현식으로 정의된 생성자 함수는 변수 호이스팅이 발생한다.
- 클래스 내의 모든 코드에는 암묵적으로 strict mode가 지정되어 실행되며 strict mode를 해제할 수 없다. 하지만 생성자 함수는 암묵적으로 strict mode가 지정되지 않는다.
- 클래스의 constructor, 프로토타입 메서드, 정적 메서드는 모드 프로퍼티 어트리뷰트 [[Enumerable]]의 값이 false다. 즉, 열거되지 않는다.
클래스 호이스팅
- 클래스 선언문 이전에 일시적 사각지대에 빠지기 때문에 호이스팅이 발생하지 않는 것처럼 동작한다.
정적 메서드와 프로토타입 메서드의 차이
- 정적 메서드와 프로토타입 메서드는 자신이 속해 있는 프로토타입 체인이 다르다.
- 정적 메서드는 클래스로 호출하고 프로토타입 메서드는 인스턴스로 호출한다.
- 정적 메서드는 인스턴스 프로퍼티를 참조할 수 없지만 프로토타입 메서드는 인스턴스 프로퍼티를 참조할 수 있다.
클래스에서 정의한 메서드 특징
- function 키워드를 생략한 메서드 축약 표현을 사용한다.
- 객체 리터럴과는 다르게 클래스에서 메서드를 정의할 때는 콤마가 필요없다.
- 암묵적으로 strict mode로 실행된다.
- 프로퍼티 어트리뷰트 [[Enumerable]]의 값이 false다.
- non-constructor이다. new 연산자와 함계 호출할 수 없다.
super 키워드
- 함수처럼 호출할 수 있고 this와 같이 식별자를 참조할 수 있는 특수한 키워드를 의미한다.
- super를 호출하면 수퍼 클래스의 constructor를 호출한다.
- 주의사항
- 서브클래스에서 constructor를 생략하지 않는 경우 서브클래스의 constructor에서 반드시 super를 호출해야한다.
- 서브클래스의 constructor에서 super를 호출하기 전에는 this를 참조할 수 없다.
- super는 반드시 서브클래스의 constructor에서만 호출한다.
- 주의사항
- super를 참조하면 수퍼 클래스의 메서드를 호출 할 수 있다.
- 메서드 축약 표현으로 정의한 함수만이 [[HomeObject]]를 갖는다.
- [[HomeObject]]프로퍼티: 슈퍼클래스를 바인딩 하는 공간
- 메서드 축약 표현으로 정의한 함수만이 [[HomeObject]]를 갖는다.
ES6 함수의 추가 기능
함수의 목적에 따른 세가지 종류
ES6 함수의 구분 | constructor | prototype | super | arguments |
---|---|---|---|---|
일반함수 | O | O | X | O |
메서드 | X | X | O | O |
화살표 함수 | X | X | X | X |
메서드
- 인스턴스를 생성할 수 없는 non-constructor이다.
- 자신을 바인딩한 객체를 가리키는 내부 슬롯 [[HomeObject]]를 갖는다.
화살표 함수
- function 키워드 대신 화살표를 사용하여 기존의 함수 정의 방식보다 간략하게 함수를 정의할 수 있는 것이다.
콜백 함수 내부에서 this가 전역 객체를 가리키는 문제를 해결하기 위한 대안으로 유용하다.
- 화살표 함수와 일반 함수의 차이
- 인스턴스를 생성할 수 없는 non-constructor다.
- 중복된 매개변수 이름을 선언할 수 없다.
- 함수 자체의 this, arguments, super, new.target 바인딩을 갖지 않는다.
- 화살표 함수 내부에서 this, arguments, super, new.target을 참조하면 스코프체인을 통해 상위 스코프의 this, arguments, super, new.target을 참조한다.
- 화살표 함수 내부에서 this를 참조하면 상위스코프의 this를 그대로 참조한다. (=lexical this)
- 렉시컬 스코프와 같이 화살표 함수의 this가 함수가 정의된 위치에 결정된다는 것을 의미한다.
Rest 파라미터
함수에 전달된 인수들의 목록을 배열로 받는다.
- 일반 매개변수와 Rest 파라미터는 함께 사용할 수 있다.
- Rest 파라미터는 반드시 마지막 파라미터이어야 한다.
- Rest 파라미터는 단 하나만 선언할 수 있다.
- Rest 파라미터는 함수 객체의 length 프로퍼티에 영향을 주지 않는다.
- 유사 배열 객체인 arguments 객체를 사용하여 배열 메서드를 사용할 경우 call메서드나 apply 메서드를 사용하여 배열을 객체로 변환을 해야하고 배열메서드를 사용해야하는 불편함이 있어 Rest 파라미터를 사용하면 가변 인자 함수의 인수 목록을 배열로 전달받으므로 번거로움을 피할 수 있다.
- 화살표 함수로 가변 인자 함수를 구현할때 Rest 파라미터를 사용한다.
배열
- 여러 개의 값을 순차적으로 나열한 자료구조를 의미한다.
- 배열이 가지고 있는 값을 요소라고 한다.
- 자바스크립트의 모든 값은 배열의 요소가 될 수 있다.
- 배열의 요소는 배열에서 자신의 위치를 나타내는 0이상의 정수인 인덱스를 가진다.
- 배열의 요소에 접근할 때 사용한다.
- 배열은 배열의 길이를 나타내는 length 프로퍼티를 갖는다.
- length 프로퍼티가 존재하여 for문을 통해 순차적으로 요소에 접근할 수 있다.
- 자바스크립트에서 배열이라는 타입이 존재하지 않으며 객체타입이다.
자바스크립트에서 배열은 배열이 아닌 이유
자료구조에서 말하는 배열은 동일한 크기의 메모리 공간이 빈틈없이 연속적으로 나열된 자료구조를 의미한다.
- 밀집 배열(dense array): 배열의 요소는 하나의 데이터타입으로 통일되어 있으며 서로 연속적으로 인접해 있는 것
- 인덱스를 통해 단 한번의 연산으로 임의의 요소에 접근(임의 접근, 시간복잡도O(1))할 수 있으며 고속으로 동작한다.
검색 대상 요소의 메모리 주소 = 배열의 시작 메모리 주소 + 인덱스 * 요소의 바이트 수
- 배열은 인덱스를 통해 효율적으로 요소에 접근할 수 있다는 장점이 있다.
- 정렬되지 않은 배열에서 특정한 요소를 검색하는 경우 배열의 모든 요소를 처음부터 특정 요소를 발견할 때 까지 차례대로 검색(선형 검색, 시간 복잡도 O(n))해야한다.
- 배열에 요소를 삽입하거나 삭제하는 경우 배열의 요소를 연속적으로 유지하기 위해 요소를 이동시켜야하는 단점이 있다.
자바스크립트의 배열은 배열의 요소를 위한 각각 메모리 공간은 동일한 크기를 갖지 않아도 되며, 연속적으로 이어져 있지 않을 수도 있다.
- 희소 배열(sparse array): 배열의 요소가 연속적으로 이어져 있지 않는 배열을 의미한다.
- 자바스크립트의 배열은 일반적인 배열의 동작을 흉내낸 특수한 객체다.
일반적인 배열과 자바스크립트의 배열의 장단점
- 일반적인 배열은 인덱스로 요소에 빠르게 접근할 수 있다. 하지만 특정 요소를 검색하거나 요소를 삽입 또는 삭제하는 경우에는 효율적이지 않다.
- 자바스크립트의 배열은 해시 테이블로 구현된 객체이므로 인덱스로 요소에 접근하는 경우 일반적인 배열보다 성능적인 면에서 느릴수 밖에 없는 구조적인 단점이 존재하지만, 특정 요소를 검색하거나 요소를 삽입 또는 삭제하는 경우네는 일반적인 배열보다 빠른 성능을 기대할 수 있다.
객체와 배열의 차이
구분 | 객체 | 배열 |
---|---|---|
구조 | 프로퍼티 키와 프로퍼티 값 | 인덱스와 요소 |
값의 참조 | 프로퍼티 키 | 인덱스 |
값의 순서 | X | O |
length 프로퍼티 | X | O |
배열의 생성방법
- 배열 리터럴
- Array 생성자 함수
- 인수가 1개이고 숫자인 경우 length 프로퍼티 값이 인수인 (희소)배열을 생성한다.
- 인수가 2개이상이거나 숫자가 아닌경우 인수를 요소로 갖는 배열을 생성한다.
- new 연산자 없이 일반함수로서 호출해도 생성자함수로 동작한다.
- Array 생성자 함수 내부에서 new.target을 확인하기 때문이다.
- Array.of 메서드
- ES6에서 도입되었다.
- 전달된 인수를 요소로 값는 배열을 생성한다.
- 인수가 1개이고 숫자이더라도 인수를 요소로 갖는 배열을 생성한다.
- Array.from 메서드
- ES6에서 도입되었다.
- 유사 배열 객체 또는 이터러블 객체를 인수로 전달받아 배열로 변환하여 반환한다.
- 두번째 인수로 전달한 함수를 통해 값을 만들면서 요소를 채울 수 있다.
유사 배열 객체와 이터러블 객체
- 유사 배열 객체: 마치 배열처럼 인덱스로 프로퍼티 값에 접근할 수 있고 length 프로퍼티를 갖는 객체를 의미한다.
- 배열처럼 for 문으로 순회 가능하다.
- 이터러블 객체: Symbol.iterator 메서드를 구현하여 for…of문으로 순회할 수 있으며, 스프레드 문법과 배열 디스트럭처링 할당의 대상으로 사용할 수 있는 객체를 의미한다.
- Array, String, Map, Set, DOM 컬렉션, arguments 등…
배열 요소의 삭제
- 배열의 특정 요소를 삭제하기 위해 delate 연산자를 사용하여 삭제할 수 있다.
- delate 연산자를 사용하여 삭제한 경우 배열은 희소배열이 된다.
- 사용하지 않는 것을 권장한다.
- Array.prototype.splice 메서드를 사용하는 것을 권장한다.
배열 메서드
Array.isArray
- 인수가 배열이면 true를 반환하고 배열이 아니면 false를 반환한다.
Array.prototype.indexOf
- 원본 배열에서 인수로 전달된 요소를 검색하여 인덱스를 반환한다.
- 중복되는 요소가 여러 개 있으면 첫 번째로 검색된 요소의 인덱스를 반환한다.
- 인수로 전달한 요소가 없으면 -1을 반환한다.
배열에 특정 요소가 존재하는지 확인하기 위해 사용한다.
- 가독성 면에서 Array.prototype.includes 메서드가 유용하다.
Array.prototype.push
- 인수로 전달받은 모든 값을 원본 배열의 마지막 요소로 추가하고 변경된 length 프로퍼티 값을 반환한다.
- 원본 배열을 직접 변경한다.
- 성능면에서 좋지 않다.
arr[arr.length] = 추가할 값;
이 더 효율적이다.
- 부수 효과가 있다.
- 스프레드 문법을 사용하는 것이 부수 효과가 없어서 좋다.
Array.prototype.pop
- 원본 배열의 마지막 요소를 제거하고 제거한 요소를 반환한다.
- 원본 배열이 빈 배열이면 undefined를 반환한다.
- 원본 배열을 직접 변경한다.
Array.prototype.unshift
- 인수로 전달받은 모든 값을 원본 배열의 선두에 요소를 추가하고 변경된 length 프로퍼티 값을 반환한다.
- 원본 배열을 직접 변경한다.
- 부수효과가 있다.
Array.prototype.shift
- 원본 배열에서 첫 번째 요소를 제거하고 제거한 요소를 반환한다.
- 원본 배열이 빈 배열이면 undefined를 반환한다.
- 원본 배열을 직접 변경한다.
Array.prototype.concat
- 인수로 전달된 값들(배열 또는 원시값)을 원본 배열의 마지막 요소로 추가한 새로운 배열로 반환한다.
- 원본 배열은 변경되지 않는다.
반환값을 반드시 변수에 할당받아야 한다.
- 스프레드 문법으로 대체가능하다.
Array.prototype.splice
- 원본 배열의 중간에 요소를 추가하거나 중간에 있는 요소를 제거하는 경우 사용한다.
- 매개변수
- start: 원본 배열의 요소를 제거하기 시작할 인덱스다. start만 지하면 원본 배열의 start 부터 모든 요소를 제거한다.
- deleteCount: start부터 제거할 요소의 개수다. 0인 경우 아무런 요소도 제거되지 않는다.(옵션)
- items: 제거한 위치에 삽입할 요소들의 목록이다. 생략할 경우 원본배열에서 요소들을 제거하기만 한다.(옵션)
- 원본 배열을 직접 변경한다.
- 배열에서 특정 요소를 제거하려면 indexOf메서드를 통해 특정 요소의 인덱스를 취득한 다음 splice메서드를 사용한다.
- filter 메서드를 사용하여 특정 요소를 제거할 수 있다. (특정 요소가 중복된 경우 모두 제거)
Array.prototype.slice
- 인수로 전달된 범위 요소들을 복사하여 배열로 반환한다.
- 매개변수
- start: 복사를 시작할 인덱스다.
- end: 복사를 종료할 인덱스다. 이 인덱스에 해당하는 요소는 복사되지 않는다. 생략하면 기본값은 length 프로퍼티 값이다.
원본 배열은 변경되지 않는다.
생성된 복사본은 얕은 복사를 통해 생성된다.
- 유사 배열 객체를 배열로 반환할 수 있다.
Array.prototype.join
- 원본 배열의 모든 요소를 문자열로 변환한 후, 구분자로 연결한 문자열을 반환한다.
- 구분자는 생략 가능하며 기본 구분자는 콤마다.
Array.prototype.reverse
- 원본 배열의 순서를 반대로 뒤집는다. 반환값은 변경된 배열이다.
- 원본 배열이 변경된다.
Array.prototype.fill
- ES6에서 도입되었다.
- 인수로 전달받은 값을 배열의 처음부터 끝까지 요소로 채운다.
- 인수
- 첫번째 인수: 요소를 채울 값
- 두번째 인수: 요소를 채우기 시작할 인덱스
- 세번째 인수: 요소 채우기를 멈출 인덱스(입력한 인덱스 이전까지)
- 원본 배열이 변경된다.
- 배열을 생성하면서 특정 값으로 요소를 생성할 수 있다.
- 모든 요소를 하나의 값만으로 채울 수 밖에 없는 단점이 있다.
- Array.from 이용하면 된다.
Array.prototype.includes
- ES7에서 도입되었다.
- 특정 요소가 포함되어있는지 확인하여 true 또는 false를 반환한다.
- 인수
- 첫번째 인수: 검색할 대상을 지정
- 두번쨰 인수: 검색을 시작할 인덱스, 생략할 경우 기본값은 0
Array.prototype.flat
- ES10에서 도입되었다.
- 인수로 전달한 깊이만큼 재귀적으로 배열을 평탄화한다.
- 인수를 생략할경우 기본값은 1이다.
- Infinity를 전달하면 중첩 배열 모두 평탄화한다.
배열 고차 함수
- 외부 상태의 변경이나 가변 데이터를 피하고 불변성을 지향하는 함수형 프로그래밍에 기반을 두고 있다.
Array.prototype.sort
배열의 요소를 정렬한다.
원본 배열을 직접 변경한다.
기본적으로 오름차순으로 요소를 정렬한다.
- 내림차순으로 하려면 sort메서드를 사용한 후, reverse 메서드를 사용한다.
기본 정렬 순서는 유니코드 코드 포인트의 순서를 따른다.
- 배열의 요소를 일시적으로 문자열로 변환 후 유니코드 코드 포인트의 순서를 기준으로 정렬한다.
숫자를 정렬하려면 정렬 순서를 정의하는 비교함수를 인수로 전달하여야한다.
1 2
// 숫자 오름차순 정렬 arr.sort((a,b) => a - b);
- 비교함수는 양수/음수/0을 반환하면 된다.
Array.prototype.forEach
- for문을 대체할 수 있는 고차함수다.
- 반복문을 추상화한 고차 함수로서 내부에서 반복문을 통해 자신을 호출한 배열을 순회하면서 수행해야할 처리를 콜백 함수로 전달받아 반복 호출하고 undefined를 반환한다.
- forEach 메서드의 콜백 함수는 forEach 메서드를 호출한 배열의 요소값과 인덱스, forEach 메서드를 호출한 배열자체(this)를 순차적으로 전달 받을 수 있다.
- 콜백 함수의 인수
- 첫번째 인수: forEach 메서드를 호출한 배열의 요소의 값
- 두번째 인수: forEach 메서드를 호출한 배열의 인덱스
- 세번째 인수: forEach 메서드를 호출한 배열(this)
- 인수
- 첫번째 인수: 콜백 함수
- 두번째 인수: forEach 메서드의 콜백 함수 내부에서 this로 사용할 객체
- 이 방식보다 화살표 함수를 사용하는 것을 권장한다.
- 반환값은 언제나 undefined다.
- 원본 배열을 변경하지 않는다.
- 콜백 함수를 통해 원본 배열을 변경할 수 있다.
- 반복문을 메서드 내부로 은닉하여 로직의 흐름을 이해하기 쉽게하고 복잡성을 해결한다.
- 배열의 모든 요소를 빠짐없이 순회하여 중간에 순회를 중단 할 수 없다.
- 희소배열의 경우 존재하지 않는 요소는 순회 대상에서 제외된다.
- for문에 비해 성능은 좋지않지만 가독성은 좋다.
- 요소가 대단히 많은 배열을 순회하거나 시간이 많이 걸리는 복잡한 코드 또는 성능이 필요한 경우가 아니라면 forEach 메서드 사용을 권장한다.
Array.prototype.map
자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복호출 하고, 콜백 함수의 반환값들로 구성된 새로운 배열을 반환한다.
- 콜백 함수의 인수
- 첫번째 인수: map 메서드를 호출한 배열의 요소의 값
- 두번째 인수: map 메서드를 호출한 배열의 인덱스
- 세번째 인수: map 메서드를 호출한 배열(this)
- 인수
- 첫번째 인수: 콜백 함수
- 두번째 인수: map 메서드의 콜백 함수 내부에서 this로 사용할 객체
- 이 방식보다 화살표 함수를 사용하는 것을 권장한다.
- 원본 배열은 변경되지 않는다.
희소배열의 경우 존재하지 않는 요소는 순회 대상에서 제외된다.
- 요소값을 다른 값으로 매핑한 새로운 배열을 생성하기 위한 고차함수이다.
- map 메서드를 호출한 배열과 map메서드가 생성하여 반환한 배열은 1:1 매핑한다.
forEach 메서드와 map 메서드의 차이
forEach: 단순히 for문을 대체하기 위한 고차 함수
map: 요소값을 다른 값으로 매핑한 새로운 배열을 생성하기 위한 고차함수
공통점: 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복호출한다.
차이점: forEach 메서드는 언제나 undefiend를 반환하고, map 메서드는 새로운 배열을 반환한다.
Array.prototype.filter
- 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복호출 하고, 콜백 함수의 반환값이 true인 요소로만 구성된 새로운 배열을 반환한다.
- 콜백 함수의 인수
- 첫번째 인수: filter 메서드를 호출한 배열의 요소의 값
- 두번째 인수: filter 메서드를 호출한 배열의 인덱스
- 세번째 인수: filter 메서드를 호출한 배열(this)
- 인수
- 첫번째 인수: 콜백 함수
- 두번째 인수: filter 메서드의 콜백 함수 내부에서 this로 사용할 객체
- 이 방식보다 화살표 함수를 사용하는 것을 권장한다.
- 원본 배열은 변경되지 않는다.
- filter 메서드로 생성하여 반환한 새로운 배열의 length 프로퍼티 값은 filter메서드를 호출한 배열의 length 프로퍼티 값과 같거나 작다.
- 자신이 호출한 배열에서 특정 요소를 제거하기 위해 사용할 수 있다.
- 중복된 요소가 모두 제거된다.
Array.prototype.reduce
- 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복호출 하고, 콜백 함수의 반환값을 다음 순회 시에 콜백 함수의 첫 번째 인수로 전달하면서 콜백함수를 호출하여 하나의 결과값을 만들어 반환한다.
- 콜백 함수의 인수
- 첫번째 인수: 초기값 또는 콜백 함수 이전 반환값
- 두번째 인수: reduce 메서드를 호출한 배열의 요소의 값
- 세번째 인수: reduce 메서드를 호출한 배열의 인덱스
- 네번째 인수: reduce 메서드를 호출한 배열(this)
- 인수
- 첫번째 인수: 콜백 함수
- 두번째 인수: 초기값
- 원본 배열은 변경되지 않는다.
- 자신을 호출한 배열의 모든 요소를 순회하며 하나의 결과값을 구해야 하는 경우에 사용한다.
- 평균 구하기, 최대값 구하기, 요소의 중복 횟수 구하기, 중첩 배열 평탄화, 중복 요소 제거 등…
- reduce 메서드를 호출할 때는 언제나 초기값을 전달하는 것이 안전하다.
Array.prototype.some
- 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복호출 하고, 콜백 함수의 반환값이 단 한 번이라도 참이면 true, 모두 거짓이면 false를 반환한다.
- 콜백 함수의 인수
- 첫번째 인수: some 메서드를 호출한 배열의 요소의 값
- 두번째 인수: some 메서드를 호출한 배열의 인덱스
- 세번째 인수: some 메서드를 호출한 배열(this)
- 인수
- 첫번째 인수: 콜백 함수
- 두번째 인수: some 메서드의 콜백 함수 내부에서 this로 사용할 객체
- 이 방식보다 화살표 함수를 사용하는 것을 권장한다.
- some 메서드를 호출한 배열이 빈 배열이면 언제나 false를 반환한다.
Array.prototype.every
- 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복호출 하고, 콜백 함수의 반환값이 모두 참이면 true, 단 한 번이라도 거짓이면 false를 반환한다.
- 콜백 함수의 인수
- 첫번째 인수: every 메서드를 호출한 배열의 요소의 값
- 두번째 인수: every 메서드를 호출한 배열의 인덱스
- 세번째 인수: every 메서드를 호출한 배열(this)
- 인수
- 첫번째 인수: 콜백 함수
- 두번째 인수: every 메서드의 콜백 함수 내부에서 this로 사용할 객체
- 이 방식보다 화살표 함수를 사용하는 것을 권장한다.
- some 메서드를 호출한 배열이 빈 배열이면 언제나 true를 반환한다.
Array.prototype.find
ES6에서 도입되었다.
- 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복호출 하고, 콜백 함수의 반환값이 true인 첫 번째 요소를 반환하고, 콜백 함수의 반환값이 true인 요소가 존재하지 않으면 undefined를 반환한다.
- 콜백 함수의 인수
- 첫번째 인수: find 메서드를 호출한 배열의 요소의 값
- 두번째 인수: find 메서드를 호출한 배열의 인덱스
- 세번째 인수: find 메서드를 호출한 배열(this)
- 인수
- 첫번째 인수: 콜백 함수
- 두번째 인수: find 메서드의 콜백 함수 내부에서 this로 사용할 객체
- 이 방식보다 화살표 함수를 사용하는 것을 권장한다.
- find 메서드의 결과값은 배열이 아닌 해당 요소의 값이다.
Array.prototype.findIndex
ES6에서 도입되었다.
- 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복호출 하고, 콜백 함수의 반환값이 true인 첫 번째 요소를 반환하고, 콜백 함수의 반환값이 true인 요소가 존재하지 않으면 -1을 반환한다.
- 콜백 함수의 인수
- 첫번째 인수: findIndex 메서드를 호출한 배열의 요소의 값
- 두번째 인수: findIndex 메서드를 호출한 배열의 인덱스
- 세번째 인수: findIndex 메서드를 호출한 배열(this)
- 인수
- 첫번째 인수: 콜백 함수
- 두번째 인수: findIndex 메서드의 콜백 함수 내부에서 this로 사용할 객체
- 이 방식보다 화살표 함수를 사용하는 것을 권장한다.
Array.prototype.flatMap
- ES10에서 도입되었다.
- map 메서드를 통해 생성된 새로운 배열을 평탄화한다.
- map 메서드와 flat 메서드를 순차적으로 실행하는 효과가 있다.
- 평탄화 깊이를 지정할 수 없고 1단계만 평탄화한다.
- 평탄화 깊이를 지정해야하면 map 메서드와 flat 메서드를 각각 호출하는 방식을 사용한다.
Number.EPSILON
ES6에서 도입되었다.
1과 1보다 큰 숫자 중에서 가장 작은 숫자와의 차이와 같다.
EPSILON은 약 2.2204460492503130808472633361816 x 10^-16이다.
부동소수점 산술 연산은 정확한 결과를 기대하기 어렵다. 정수는 2진법으로 오차없이 저장 가능하지만 부동소수점을 표현하기위해 널리 쓰이는 표준인 IEEE754는 2진법으로 변환했을 때 무한소수가 되어 미세한 오차가 발생할 수 밖에 없는 구조적 한계가 있다.
1 2 3 4 5 6 7 8
0.1 + 0.2; // 0.30000000000000004 0.1 + 0.2 === 0.3; // false function isEqual(a, b) { // a와 b를 뺀 값의 절대값이 Number.EPSILON보다 작으면 같은 수로 인정된다. return Math.abs(a - b) < Number.EPSILON; } isEqual(0.1 + 0.2, 0.3)
- EPSILON 메서드는 부동 소수점으로 인해 발생하는 오차를 해결하기 위해 사용한다.
정규 표현식
일정한 패턴을 가진 문자열의 집합을 표현하기 위해 사용하는 형식 언어
문자열을 대상으로 패턴 매칭 기능을 제공한다.
- 패턴 매칭 기능: 특정 패턴과 일치하는 문자열을 검색하거나 추출 또는 치환할 수 있는 기능을 의미한다.
정규 표현식을 사용하면 반복문과 조건문 없이 패턴을 정의하고 테스트하는 것으로 간단히 체크할 수 있다.
- 정규표현식은 주석이나 공백을 허용하지 않고 여러가지 기호를 혼합하여 사용하기 때문에 가독성이 좋지 않다는 단점이 있다.
1
const reexp = /is/i; // /(시작패턴) is(패턴) /(종료패턴) i(플래그)
RegExp 메서드
RegExp.prototype.exec
- 인수로 전달받은 문자열에 대해 정규표현식의 패턴을 검색하여 매칭 결과를 배열로 반환하고, 매칭 결과가 없으면 null을 반환한다.
- g플래그를 지정해도 첫번째 매칭 결과만 반환한다.
RegExp.prototype.test
- 인수로 전달받은 문자열에 대해 정규표현식의 패턴을 검색하여 매칭 결과를 불리언 값으로 반환한다.
RegExp.prototype.math
- 대상 문자열과 인수로 전달받은 정규 표현식과의 매칭결과를 배열로 반환한다.
- g 플래그가 지정되면 모든 매칭 결과를 배열로 반환한다.
String 메서드
- String 객체의 메서드는 언제나 새로운 문자열을 반환한다.
- 문자열은 원시 값이기 때문에 String 래퍼 객체도 읽기 전용 객체로 제공된다.
String.prototype.search
- 대상 문자열에서 인수로 전달받은 정규 표현식과 매치하는 문자열을 검색하여 일치하는 문자열의 인덱스를 반환하고 검색에 실패하면 -1을 반환한다.
String.prototype.startsWith
- ES6에서 도입되었다.
대상 문자열이 인수로 전달받은 문자열로 시작하는지 확인하여 그결과를 true 또는 false로 반환한다.
- 인수
- 첫번째 인수: 검색할 문자열
- 두번째 인수: 검색을 시작할 인덱스(옵션)
String.prototype.endsWith
- ES6에서 도입되었다.
- 대상 문자열이 인수로 전달받은 문자열로 끝나는지 확인하여 그결과를 true 또는 false로 반환한다.
- 인수
- 첫번째 인수: 검색할 문자열
- 두번째 인수: 검색할 문자열의 길이(옵션)
String.prototype.charAt
- 대상 문자열에서 인수로 전달받은 인덱스에 위치한 문자를 검색하여 반환한다.
- 인덱스는 문자열의 범위어야 한다.
- 인덱스가 문자열 범위를 벗어난 정수인 경우 빈 문자열을 반환한다.
- 유사한 문자열 메서드로 charCodeAt과 codePointAt이 있다.
String.prototype.substring
- 대상 문자열에서 첫 번째 인수로 전달받은 인덱스에 위치하는 문자부터 두 번째 인수로 전달받은 인덱스에 위치하는 문자의 바로 이전문자까지의 부분 문자열을 반환한다.
- 인수
- 첫번째 인수 > 두번째 인수: 두인수는 교환된다.
- 인수 < 0 또는 NaN: 0으로 취급된다.
- 인수 > 문자열의 길이: 문자열의 길이로 취급된다.
String.prototype.toUpperCase
- 대상 문자열을 모두 대문자로 변경한 문자열을 반환한다.
String.prototype.toLowerCase
- 대상 문자열을 모두 소문자로 변경한 문자열을 반환한다.
String.prototype.trim
- 대상 문자열 앞뒤에 공백문자가 있을 경우 이를 제거한 문자열을 반환한다.
- String.prototype.trimStart
- 대상 문자열 앞에 공백 문자가 있을 경우 이를 제거한 문자열을 반환한다.
- String.prototype.trimEnd
- 대상 문자열 뒤에 공백 문자가 있을 경우 이를 제거한 문자열을 반환한다.
- replace 메서드에 정규 표현식을 인수로 전달하여 공백문자를 제거할 수 있다.
String.prototype.repeat
- ES6에서 도입되었다.
- 대상 문자열을 인수로 전달받은 정수만큼 반복해 연결한 새로운 문자열을 반환한다.
- 인수로 전달받은 정수가 0이면 빈문자열을 반환한다.
- 인수로 전달받은 정수가 음수면 RangeError를 발생시킨다.
- 인수를 생략하면 기본값 0이 설정된다.
String.prototype.replace
- 대상 문자열에서 첫 번째 인수로 전달받은 문자열 또는 정규표현식을 검색하여 두 번째 인수로 전달한 문자열로 치환한 문자열을 반환한다.
- 검색된 문자열이 여럿 존재할 경우 첫 번째로 검색된 문자열만 치환한다.
- 특수한 교체 패턴을 사용할 수 있다.
- $&: 검색된 문자열
- 두 번째 인수에 치환 함수를 전달 할 수 있다.
String.prototype.split
- 대상 문자열에서 첫 번째 인수로 전달한 문자열 또는 정규표현식을 검색하여 문자열로 구분한 후 분리된 각 문자열로 이루어진 배열을 반환한다.
- 인수로 빈 문자열을 전달하면 각 문자를 모두 분리한다.
- 인수를 생략하면 대상 문자열 전체를 단일 요소로 하는 배열을 반환한다.
- 두번째 인수로 배열의 길이를 지정할 수 있다.
심벌(Symbol)
- ES6에서 도입된 7번째 데이터 타입으로 변경 불가능한 원시 타입의 값
- 심벌 값은 다른 값과 중복되지 않는 유일무이한 값이다.
- 이름의 충돌 위험이 없는 유일한 프로퍼티 키를 만들기 위해 사용한다.
- 프로퍼티 키로 사용할 수 있는 빈 문자열을 포함하는 모든 문자열 또는 심벌 값이다.
- 프로퍼티 키로 사용하여 프로퍼티를 생성하면 외부에 노출할 필요가 없는 프로퍼티를 은닉할 수 있다.
- ES6에서 도입된 Object.getOwnPropertySymbols 메서드를 사용하면 심벌 값을 프로퍼티로 사용하여 생성한 프로퍼티를 찾을 수 있다.
- 심벌 값으로 프로퍼티 키를 생성하여 표준 빌트인 객체를 확장하면 표준 빌트인 객체의 기존 프로퍼티 키와 충돌하지 않고 표준 사양의 버전이 올라감에 따라 추가될지 모르는 어떤 프로퍼티 키와도 충돌한 위험이 없어 안전하게 표준 빌트인 객체를 확장할 수 있다.
- 중복되지 않는 상수 값을 생성하는 것은 몰론 기존에 작성된 코드에 영향을 주지않고 새로운 프로퍼티를 추가하기위해, 즉 하위 호환성을 보장하기 위해 도입되었다.
Symbol 함수
심벌 값은 외부로 노출되지 않아 확인할 수 없으며, 다른 값과 절대 중복되지 않는 유일 무일한 값이다.
1
const mySymbol = Symbol();
new 연산자와 함께 호출하지 않는다.
선택적으로 문자열을 인수로 전달할 수 있다.
- 이 문자열은 생성된 심벌 값에 대한 설명으로 디버깅 용도로만 사용되며, 심벌 값 생성에 어떠한 영향도 주지않는다.
- 설명이 같더라도 생성된 심벌 값은 유일무이한 값이다.
암묵적으로 문자열이나 숫자 타입으로 변환되지 않는다.
- 불리언 타입으로는 암묵적 타입 변환이 된다.
Symol.for / Symbol.keyFor 메서드
- Symol.for 메서드: 인수로 전달 받은 문자열을 키로 사용하여 키와 심벌 값의 쌍들이 저장되어있는 전역 심벌 레지스트리에서 해당 키와 일치하는 심벌 값을 검색한다.
- 검색 성공시: 새로운 심벌 값을 생성하지 않고, 검색된 심벌 값을 반환한다.
- 검색 실패시: 새로운 심벌 값을 생성하여 Symol.for 메서드의 인수로 전달된 키로 전역 심벌 레지스트리에 저장한 후, 생성된 심벌값을 반환한다.
애플리케이션 전역세서 중복되지 않는 유일무이한 상수인 심벌 값을 단 하나만 생성하여 전역 심벌 레지스트리를 통해 공유할 수 있다.
- Symol.keyFor 메서드: 전역 심벌 레지스트리에 저장된 심벌 값의 키를 추출할 수 있다.
enum
- 명명된 숫자 상수의 집합으로 열거형이라고 부른다.
- 자바스크립트는 enum을 지원하지 않지만 타입스크립트는 enum을 지원한다.
- 자바스크립트에서 enum을 흉내내어 사용하려면 객체 변경을 방지하기 위해 객체를 동결하는 Object.freeze 메서드와 심벌 값을 사용한다.
심벌과 프로퍼티 키
- 심벌 값을 프로퍼티 키로 사용하려면 프로퍼티 키로 사용할 심벌값에 대괄호를 사용해야한다. 프로퍼티에 접근할 때도 대괄호를 사용해야한다.
Well-known Symbol
- 자바스크립트가 기본 제공하는 빌트인 심벌 값을 ECMAScript 사양에서 부르는 용어이다.
- 자바스크립트 엔진의 내부 알고리즘에 사용된다.
- 순회 가능한 빌트인 이터러블은 Symbol.iterator를 키로 갖는 메서드를 가지며 Symbol.iterator를 호출하면 이터레이터를 반환하도록 ECMAScript 사양에 규정되어있다.
- 빌트인 이터러블은 이터레이션 프로토콜에 준수한다.
- 빌트인 이터러블이 아닌 일반 객체를 이터러블처럼 동작하도록 구현하고 싶다면 이터레이션 프로토콜을 따르면 된다.
- Symbol.iterator를 키로 갖는 메서드를 객체에 추가하고 이터레이터를 반환하도록 구현한다면 그 객체는 이터러블이 된다.
이터레이션 프로토콜
- ES6에 도입되었다.
- 순회 가능한 데이터 컬렉션(자료구조)을 만들기 위해 ECMAScript 사양에 정의하여 미리 약속한 규칙이다.
- 순회 가능한 데이터 컬렉션을 이터레이션 프로토콜에 준수하는 이터러블로 통일하여 for … of 문, 스프레드 문법, 배열 디스트럭처링 할당의 대상으로 사용할 수 있도록 일원화했다.
- 이터레이션 프로토콜의 종류
- 이터러블 프로토콜
- Well-known Symbol인 Symbol.iterator를 프로퍼티 키로 사용한 메서드를 직접 구현하거나 프로토타입 체인을 통해 상속 받은 Symbol.iterator 메서드를 호출하면 이터레이터 프로토콜을 준수한 이터레이터를 반환한다. 이러한 규약을 이터러블 프로토콜이라 하며, 이터러블 프로토콜을 준수한 객체를 이터러블이라 한다. 이터러블은 for …of 문’으로 순회할 수 있으며 스프레 드 문법’과 배열 디스트럭처링 할당’의 대상으로 사용할 수 있다.
- 이터레이터 프로토콜
- 이터러블의 Symbol.iterator 메서드를 호출하면 이터레이터 프로토콜을 준수한 이터레이터를 반환한다. 이터레이터는 next 메서드를 소유하며 next 메서드를 호출하면 이터러블을 순회하며 value와 done 프로퍼티를 갖는 이터레이터 리절트 객체를 반환한다. 이러한 규약을 이터레이터 프로토콜이라 하며, 이터레이터 프로토콜을 준수한 객체를 이터레이터라 한다. 이터레이터는 이터러블의 요소를 탐색하기 위한 포인터 역할을 한다.
- 이터러블 프로토콜
이터러블
- 이티러블 프로토콜을 준수한 객체를 이터러블이라 한다.
- Symbol.iterator를 프로퍼티 키로 사용한 메서드를 직접 구현하거나 프로토타입 체인을 통해 상속받은 객체를 말한다.
- 배열, 문자열, Map, Set 등은 이터러블이다.
이터러블은 for … of 문으로 순회할 수 있으며, 스프레드 문법과 배열 디스트럭처링 할당의 대상으로 사용할 수 있다.
- Symol.iterator 메서드를 직접 구현하지 않거나 상속받지 않은 일반 객체는 이터러블 프로토콜을 준수한 이터러블이 아니다.
- 객체는 for … of 문으로 순회할 수 없으며 스프레드 문법과 배열 디스트럭처링 할당의 대상으로 사용할 수 없다.
- 일반 객체에는 스프레드 문법의 사용을 허용한다.
이터레이터
- 이터러블의 Symbol.iterator 메서드를 호출하면 이터레이터 프로토콜을 준수한 이터레이터를 반환한다.
- 이터러블의 Symbol.iterator 메서드가 반환한 이터레이터는 next 메서드를 갖는다.
- 이터레이터의 next 메서드는 이터러블의 각 요소를 순회하기 위해 포인터의 역할을 한다.
- next 메서드를 호출하면 순차적으로 한 단계씩 순회하며 순회 결과를 나타내는 이터레이터 리절드 객체를 반환한다.
- 이터레이터의 next 메서드가 반화하는 이터레이터 리절트 객체의 value 프로퍼티는 현재 순회 중인 이터러벌의 값을 나타내며 done 프로퍼티는 이터러블의 순회 완료 여부를 나타낸다.
빌트인 이터러블
- Array, String, Set, TypeArray, arguments, DOM 컬렉션(NodeList, HTMLCollection)
for … of 문
- 이터러블을 순회하면서 이터러블의 요소를 변수에 할당한다.
- 내부적으로 이터레이터의 next 메서드를 호출하여 이터러블을 순회하며 next 메서드가 반환한 이터레이터 리절트 객체의 value 값을 for … of 문의 변수에 할당한다.
- 이터레이터 리절트 객체의 done 프로퍼티 값이 false이면 이터러블 순회를 계속하고 true이면 이터러블의 순회를 중단한다.
이터러블과 유사 배열 객체
- 유사 배열 객체는 Symbol.iterator 메서드가 없어 for … of 문으로 순회할 수 없다.
- 모든 유사 배열 객체가 이터러블인 것은 아니다.
- Array.from 메서드를 사용하여 배열로 변환할 수 있다.
- 배열은 이터러블이다.
이터레이션 프로토콜의 필요성
- 이터레이션 프로토콜을 준수하는 Array, String, Map, Set, TypeArray(Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Int16Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array), DOM 컬렉션(NodeList, HTMLCollection), arguments들은 for … of 문, 스프레드 문법, 배열 디스트럭처링 할당 등에 사용할 수 있다.
- 이터러블은 for … of 문, 스프레드 문법, 배열 디스트럭처링 할당과 같은 데이터 소비자에 의해 사용되므로 데이터 공급자 역할을 한다고 할 수 있다.
- 이터레이션 프로토콜은 다양한 데이터 공급자가 하나의 순회 방식을 갖도록 규정하여 데이터 소비자가 효율적으로 다양한 데이터 공급자를 사용할 수 있도록 데이터 소비자와 데이터 공급자를 연결하는 인터페이스 역할을 한다.
사용자 정의 이터러블
- 이터레이션 프로토콜을 준수하지 않는 일반 객체도 이터레이션 프로토콜을 준수하도록 구현하면 사용자 정의 이터러블이 된다.
- 예시로 피보나치 수열을 구현한 사용자 정의 이터러블이 있다.
- 사용자 정의 이터러블은 이터레이션 프로토콜을 준수하도록 Symbol.iterator 메서드를 구현하고 Symbol.iterator 메서드가 next 메서드를 갖는 이터레이터를 반환하도록 한다. 그리고 이터레이터의 next 메서드는 done과 value 프로퍼티를 가지는 이터레이터 리절트 객체를 반환한다.
- for … of 문은 done 프로퍼티가 true가 될 때까지 반복하며 done 프로퍼티가 true가 되면 반복을 중지한다.
이터러블이면서 이터레이터인 객체 생성
- Symbol.iterator 메서드를 호출하지 않아도 된다.
- Symbol.iterator 메서드와 next 메서드를 소유한 이터러블이면서 이터레이터이다.
지연 평가
- 데이터가 필요한 시점 이전까지 데이터를 생성하지 않다가 데이터가 필요한 시점이 되면 비로소 데이터를 생성하는 기법이다.
- 평가 결과가 필요할 때까지 평가를 늦추는 기법이다.
- 불필요한 데이터를 미리 생성하지 않고 필요한 데이터를 필요한 순간에 생성하므로 빠른 실행 속도를 기대할 수 있고 불필요한 메모리를 소비하지 않으며 무한도 표현할 수 있다는 장점이 있다.
스프레드 문법(...
)
- 하나로 뭉쳐 있는 여러 값들의 집합을 전개하여 개별적인 값들의 목록으로 만드는 것이다.
- for … of 문으로 순회 할 수 있는 이터러블이 스프레드 문법을 사용할 수 있다.
- 스프레드 문법의 결과는 값이 아니다.
- 스프레드 문법의 결과는
...
이 피연산자를 연산하여 값을 생성하는 연산자가 아니라서 변수에 할당할 수 없다.
- 스프레드 문법의 결과는
- 스프레드 문법의 결과물은 값으로 사용할 수 없고 쉼표로 구분한 값의 목록을 사용하는 문맥에서만 사용할 수 있다.
- 함수 호출문의 인수 목록
- Math.max 메서드 → 스프레드 문법 이전에는 apply 메서드를 사용하여 배열을 펼쳐서 요소들의 목록을 함수의 인수로 전달했다.
- 배열 리터럴의 요소 목록
- concat 메서드를 대신하여 사용할 수 있다.
- splice 메서드에 활용하여 간결하고 가독성 좋게 표현할 수 있다.
- slice 메서드를 사용한 것보다 배열을 간결하고 가독성 좋게 얕은 복사를 할 수 있다.
- apply 메서드와 call 메서드를 사용하여 이터러블을 배열로 변환한 것보다 더 간편하게 이터러블을 배열로 변환할 수 있다.
- 이터러블이 아닌 유사 배열 객체는 스프레드 문법의 대상이 될 수 없다. → 이터러블이 아닌 유사 배열 객체를 배열로 변경하려면 Array.from 메서드를 사용한다.
- 객체 리터럴의 프로퍼티 목록
- 스프레드 프로퍼티 제안으로 일반 객체를 대상으로도 스프레드 문법의 사용을 허한다.
- 제안 이전에는 Object.assgin 메서드로 여러 개의 객체를 병합하거나 특정 프로퍼티를 변경 또는 추가했다.
- 함수 호출문의 인수 목록
디스트럭처링 할당(구조 분해 할당)
구조화된 배열과 같은 이터러블 또는 객체를 디스트럭처링(비구조화, 구조파괴)하여 1개 이상의 변수에 개별적으로 할당하는 것을 의미한다.
배열과 같은 이터러블 또는 객체에서 필요한 값만 추출하여 변수에 할당할 때 유용하다.
배열 디스트럭처링 할당
배열 디스트럭처링 할당의 기준은 배열의 인덱스다.
순서대로 할당되며 변수의 개수와 이터러블의 요소 개수가 반드시 일치할 필요는 없다.
배열 디스트럭처링 할당을 위한 변수에 기본값을 설정할 수 있다.
- 기본값보다 할당된 값이 우선된다.
배열 디스트럭처링 할당은 배열과 같은 이터러블에서 필요한 요소만 추출하여 변수에 할당하고 싶을 때 유용하다.
변수에 Rest 요소 …을 사용할 수 있다.
- 반드시 마지막에 위치해야한다.
객체 디스트럭처링 할당
- 할당 기준은 프로퍼티 키다.
- 순서가 의미가 없으며 선언된 변수 이름과 프로퍼티 키가 일치하면 할당된다.
- 프로퍼티 축약 표현을 통해 선언해도 된다.
- 객체의 프로퍼티 키와 다른 변수 이름으로 프로퍼티를 할당 받으려면 변수를 키와 값 형식으로 사용하고 값이 변수가 된다.
- 변수에 기본값을 설정할 수 있다.
- 객체에서 프로퍼티 키를 필요한 프로퍼티 값만 추출하여 변수에 할당하고 싶을 때 유용하다.
- 객체를 인수로 전달받는 함수의 매개변수에도 사용할 수 있다.
- 배열의 요소가 객체인 경우 배열 디스트럭처링 할당과 객체 디스트럭처링 할당을 혼용할 수 있다.
- 변수에 Rest 요소 …을 사용할 수 있다.
- 반드시 마지막에 위치해야한다.
- 할당 기준은 프로퍼티 키다.
Set
중복되지 않는 유일한 값들의 집합이다.
Set 객체는 이터러블이다.
배열과 Set의 차이
구분 배열 set 객체 동일한 값을 중복하여 포함할 수 있다. O X 요소 순서에 의미가 있다. O X 인덱스로 요소에 접근할 수 있다. O X
Set은 수학적 집합을 구현하기 위한 자료구조이다.
- 교집합, 합집합, 차집합, 여집합 등을 구현할 수 있다.
Set 객체 생성
- Set 생성자 함수를 사용하여 생성한다.
- 이터러블을 인수로 전달받아 Set 객체를 생성한다. 이때 이터러블의 중복된 값은 Set 객체에 요소로 저장되지 않는다.
- Set 객체의 특성을 활용하여 배열에서 중복된 요소를 제거할 수 있다.
요소 개수 확인
- Set.prototype.size 프로퍼티를 사용한다.
- 요소 개수는 변경 할 수 없다(getter함수만 존재하기 때문에)
요소 추가
- Set.prototype.add 메서드를 사용한다.
- 새로운 요소가 추가된 Set 객체를 반환한다.
- 연속적으로 호출할 수 있다.
- 중복된 요소의 추가는 허용하지 않는다. 에러가 발생하지않고 무시된다.
- 일치 비교 연산자(
===
)를 사용하면 NaN과 NaN는 false라고 평가하지만 Set 객체는 같다고 평가하여 중복 추가를 허용하지 않는다. +0과 -0은 true로 평가하여 중복 추가하지 않는다. - set 객체는 객체나 배열과 같이 자바스크립트의 모든 값을 요소로 저장할 수 있다.
요소 존재 여부 확인
- Set.prototype.has 메서드를 사용한다.
- 특정 요소가 존재할때 사용한다.
- 특정요소의 존재 여부를 나타내는 불리언 값을 반환한다.
요소 삭제
- Set.prototype.delate 메서드를 사용한다.
- 삭제 성공 여부를 나타내는 불리언 값을 반환한다.
- 인수에 삭제하려는 요소값을 전달한다.
- 존재하지 않는 Set 객체의 요소를 삭제하려 하면 에러 없이 무시된다.
- 연속적으로 호출할 수 없다.
요소 일괄 삭제
- Set.prototype.clear 메서드
- 모든 요소를 일괄 삭제할때 사용한다.
- 언제나 undefined를 반환한다.
요소 순회
- Set.prototype.forEach 메서드를 사용한다.
- 콜백 함수 인수
- 첫 번째 인수: 현재 순회 중인 요소값
- 두 번째 인수: 현재 순회 중인 요소값
- 세 번째 인수: 현재 순회 중인 Set 객체 자체
- for … of 문으로 순회 가능하다.
- 스프레드 문법과 배열 디스트럭처링 대상이 될 수 있다.
- 요소의 순서에 의미를 갖지 않지만, Set 객체를 순회하는 순서는 요소가 추가된 순서를 따른다.
- 다른 이터러블의 순회와 호환성을 유지하기 위해서이다.
집합 연산
- 교집합
- Set.prototype.intersection 메서드
- 공통 요소로 구성된다.
- 합집합
- Set.prototype.union 메서드
- 중복 없는 모든 요소로 구성된다.
- 차집합
- Set.prototype.difference
- 차집합 A-B는 집합 A에는 존재하지만 집합 B에는 존재하지 않는 요소로 구성된다.
- 부분 집합과 상위 집합
- Set.prototype.isSuperset
- 집합 A가 집합 B에 포함되는 경우 집합 A는 집합 B의 부분집합이며, 집합 B는 집합 A의 상위 집합이다.
Map
키와 값의 쌍으로 이루어진 자료구조이다.
Map 객체는 이터러블이다.
객체와 Map의 차이점
구분 객체 Map 객체 키로 사용할 수 있는 값 문자열 또는 심벌 값 객체를 포함한 모든 값 이터러블 X O 요소 개수 확인 Object.kets(obj).length map.size
Map 객체 생성
- Map 생성자 함수로 생성한다.
- 인수를 전달하지 않으면 빈 Map 객체가 생성된다.
- Map 생성자 함수는 이터러블을 인수로 전달받아 Map 객체를 생성한다. 인수로 전달되는 이터러블은 키와 값의 쌍으로 이루어진 요소들로 구성되어야 한다.
- 중복된 키를 갖는 요소가 존재할 수 없다.
요소 개수 확인
- Map.prototype.size 프로퍼티를 사용한다.
- 요소 개수를 변경할 수 없다.
- getter 함수만 존재하는 접근자 프로퍼티
요소 추가
- Map.prototype.set 메서드를 사용한다.
- 연속적으로 호출할 수 있다.
- 중복된 키를 갖는 요소를 추가하면 값이 덮어 씌어진다. 에러는 발생하지 않는다.
- NaN과 NaN을 같다고 평가한다.
- 객체를 포함한 모든 값을 키로 사용할 수 있다.
요소 취득
- Map.prototype.get 메서드를 사용한다.
- 특정 요소를 취득할 때 사용한다.
- 인수로 전달한 키를 갖는 값을 반환한다. 만약 요소가 존재하지 않으면 undefined를 반환한다.
요소 존재 여부 확인
Map.prototype.has 메서드를 사용한다.
- 특정 요소가 존재하는지 확인 할때 사용한다.
- 특정 요소의 존재 여부를 나타내는 불리언 값을 반환한다.
요소 삭제
- Map.prototype.delate 메서드를 사용한다.
- 삭제 성공 여부를 나타내는 불리언 값을 반환한다.
- 존재하지 않는 키로 Map 객체의 요소를 삭제하려 하면 에러 없이 무시된다.
- 연속적으로 호출할 수 없다.
요소 일괄 삭제
- Map.prototype.clear 메서드
- 모든 요소를 일괄 삭제할때 사용한다.
- 언제나 undefined를 반환한다.
요소 순회
- Map.prototype.forEach 메서드를 사용한다.
- 콜백 함수 인수
- 첫 번째 인수: 현재 순회 중인 요소값
- 두 번째 인수: 현재 순회 중인 요소키
- 세 번째 인수: 현재 순회 중인 Map 객체 자체
- for … of 문으로 순회 가능하다.
- 스프레드 문법과 배열 디스트럭처링 대상이 될 수 있다.
- Map 객체는 이터러블이면서 동시에 이터레이터 객체를 반환하는 메서드를 제공한다.
- keys, values, entries
- 요소의 순서에 의미를 갖지 않지만, Set 객체를 순회하는 순서는 요소가 추가된 순서를 따른다.
- 다른 이터러블의 순회와 호환성을 유지하기 위해서이다.