자바스크립트 ES6+

1차 카테고리
JS
2차 카테고리
ES6
생성 일시
2025/02/10 11:48
최종 편집 일시
2025/02/13 07:56
발행여부
published

1. let, const

1-1. 변수 구분

로컬 변수, 글로벌 변수를 구분하는 이유는? → 기능과 목적이 다르기 때문
글로벌 변수의 기능과 목적
다른 js 파일에서 변숫값 공유
파일에서 공통 변수 개념으로 사용
처리 속도가 떨어진다.
로컬 변수의 기능, 목적
빠르게 식별자를 해결하기 위해 가까운 스코프의 변수를 사용하려는 것.

1-2. 블록 스코프 유형

function 블록
try-catch 블록
catch()에서는 try 밖의 변수를 사용한다.
swtich-case

1-3. let 변수 개요, let 변수 선언, 블록스코프

1-3-1. let 변수란

블록 스코프를 가진 변수이다. 변수가 선언된 블록이 스코프
스코프 적용 기준
블록 { }, 문, 표현식

1-4. let 변수와 var 변수 차이

var node = document.querySelector('.sports'); //for (let i = 0; i < node.children.length; i += 1) { for (var i = 0; i < node.children.length; i += 1) { node.children[i].onclick = function (event) { event.target.style.backgroundColor = 'yellow'; console.log(i); }; }
JavaScript
복사
var를 쓰게 되면 해당 이벤트 핸들러 함수가 실행이 될 때, 실행 컨텍스트의 이미 증가된 i를 참조한다.
반면에 let 은 독립적인 렉시컬 환경이 생성이 된다.

1-5. let 변수와 this

var music = '음악' let sports = '축구' console.log(this.music, this.sports)
JavaScript
복사
글로벌 오브젝트에서 let 변수를 this로 참조 불가.
글로벌 오브젝트에서 varlet 변수가 설정되는 위치 구조
var globalVar = '글로벌'; let globalLet = '블록'; console.log(this.globalVar, this.globalLet) // 글로벌 undefined
JavaScript
복사
let 변수를 블록 안에 작성해야 하지만 블록이 없으므로 엔진이 블록을 만들고, 이를 스코프로 사용하여 설정하는 개념이다. 브라우저 개발자 도구에서 생성된 Script는 하나의 블록 개념으로 <script>에 작성한 모든 파일에서 공유한다. let을 쓴다고 공유를 못하는 것이 아니다.
globalLet은 window 오브젝트에 설정되지 않으므로 undefined가 출력된다.
글로벌 오브젝트의 var 변수와 let 변수의 차이. 저장되는 영역이 다르다.

1-6. js 파일 다수 사용

모든 js 파일에서 글로벌 오브젝트에 작성한 var 변수와 let 변수를 공유
블록 안에 작성하면 공유하지 않는다.
글로벌 오브젝트에 작성
var: window에 설정하고 공유한다.
let: Script에 설정하고 공유한다.
함수에 작성
var, let 변수: Local
{ let 변수 } : Block

1-7. 호이스팅

let에서는 호이스팅이 일어나지 않는다.
엄밀히 말하면 호이스팅은 일어나지만, 엔진이 변수로 인식하지 않는다. 따라서 사용할 수 없다. 즉, 초기화 단계에 변수가 값을 가지고 있다면 호이스팅 값이 없다면 호이스팅은
ES5에서의 실행 컨텍스트 처리 순서를 생각해보면 다음과 같다.
1.
함수 선언문 설정
2.
변수 이름을 바인딩. 변숫값은 undefined
3.
소스코드 실행

1-8. const

값을 바꿀 수 없는 변수 선언
재할당이 금지된다. 하지만 오브젝트의 프로퍼티 값을 바꿀 수 있다.

2. Arrow Function

function(){} 축약 형태이지만 this 참조가 다르다.

2-1. 화살표 함수 구조

prototype, constructor가 없다. 메소드를 연결해서 확장할 수 없다. 생성자 함수로 쓸 수 없다. → 가볍게 쓸 수 있다. 사용하지도 않는 것을 쓰지 말자
argument를 사용할 수 없다. rest 파라미터를 사용한다.

2-2. 화살표 함수와 this

호출 방법에 따른 this 바인딩

메서드 호출 (객체의 프로퍼티로 호출) → this는 해당 객체
일반 함수 호출 → thisundefined (strict mode) 또는 window (non-strict)
화살표 함수는 자신이 속한 스코프의 this를 사용한다.
생성자 호출 (new 키워드) → this는 새로 생성된 객체
call, apply, bind를 통한 호출 → this를 명시적으로 지정 가능

this의 문제 1

'use strict' function book(){ function getPoint(){ console.log(this); } getPoint(); // window.getPoint() } window.book(); // undefined
JavaScript
복사
1.
strict 모드에서는 호출하는 함수 앞에 오브젝트를 작성해야 한다. 이렇게 작성하지 않으면 book() 함수 안에서 this 값이 undefined다.
2.
getPoint()처럼 window를 앞에 작성하지 않으면 getPoint() 안에서 this 값이 undefined다.
strict 모드에서는 함수 앞에 오브젝트를 작성하지 않으면 this 바인딩 컴포넌트에 undefined 가 설정 되므로 thiswindow를 참조할 수 없음.

화살표 함수로 this 문제1 해결

'use strict' var point = 100; function sports(){ const getPoint = () => { console.log(this.point); } getPoint(); // window.getPoint() } window.sports(); // 100
JavaScript
복사
화살표 함수로 작성하면 getPoint()로 호출할 수 있다. getPoint() 화살표 함수 안에서 this가 undefined가 아니라 글로벌 오브젝트를 참조한다.

this의 문제 2

const obj = { value: 100, getValue: function () { setTimeout(function () { console.log(this.value); // ❌ undefined (this가 obj가 아님!) }, 1000); } }; obj.getValue();
JavaScript
복사
setTimeout에서의 함수는 일반함수이므로 window 오브젝트를 참조한다.
이런 호출 방식에 따라 this 바인딩이 달라지는 문제들 인해서 화살표 함수가 나오게 되었다.
마찬가지로 화살표 함수를 쓰면 해결이 된다.

화살표 함수는 this를 가지고 있지 않다.

var point = 100; const book = { getPoint: () => { console.log("this.point", this.point); } }; book.getPoint(); // 100
JavaScript
복사
1.
화살표 함수인 book.getPoint()를 호출하면 크롬 개발자 도구에서 Local에 this: undefined가 표시된다.
2.
화살표 함수는 함수에 this를 갖고 있지 않기 때문이다.
3.
이때 this가 window 오브젝트를 참조한다. (상황에 따라 다르지만 대부분 window 오브젝트를 참조한다.)
this가 window 오브젝트를 어떻게 참조할까?
→ this가 정적 스코프를 참조하기 때문이다.

this 정적 스코프 참조

var title = "책"; const book = { show:() => console.log(this.title) }; book.show();
JavaScript
복사
전역 실행 컨텍스트가 생성이 된 이후 show 함수의 실행 컨텍스트가 생성이 되므로 스코프는 전역으로 설정이 된다.
오브젝트의 바인딩된 스코프의 this를 화살표 함수에서 this로 사용한다. 화살표 함수는 this가 없기 때문에 자신이 속한 스코프의 this를 사용한다.
그래서 window 오브젝트를 참조한다.

2-3. 화살표 함수와 인스턴스

var point = 200; const Point = function(){ this.point = 100; } Point.prototype.getPoint = () => { console.log(this.point); } new Point().getPoint();
JavaScript
복사
this가 글로벌 오브젝트를 참조한다.(이미 인스턴스 생성 이후 함수를 호출하는 것!)
화살표 함수이기 때문에 자신이 속한 스코프의 this를 참조한다.
const Point = function(){ this.point = 100; } Point.prototype.getPoint = function(){ const add = () => this.point + 20; console.log(add()); [1, 2].forEach((value) => { console.log(this.point + value); } } new Point().getPoint();
JavaScript
복사
getPoint()의 this는 인스턴스를 참조한다. getPoint() 안에서 화살표 함수를 사용했으므로 getPoint()의 스코프를 따라간다. → this가 Point 인스턴스를 참조.
원래는 일반함수가 아니라 메소드라고 해야지 맞지 않나. 여튼 getPoint() 실행 컨텍스트가 생성이 된 상태에서 화살표 함수가 실행되므로 자신이 속한 스코프의 this를 참조한다. → this가 Point 인스턴스를 참조.

정리

prototype이 없으므로 함수가 가볍다.
constructor가 없으므로 new 연산자로 인스턴스 생성할 수 없다.
화살표 함수에 this가 없다. 화살표 함수가 속한 스코프의 this를 화살표 함수에 바인딩. 바인딩 된 this 참조가 바뀌지 않는다. 일반 함수는 call() 등으로 바꿀 수 있다.

즉, 화살표 함수는 메소드보다 함수로 사용하는 것이 효율성이 높다.

3. 이터레이션

심볼에서 더 자세히 다룬다.
이터레이션의 사전적 의미는 반복이다.
for문의 반복 개념과는 차이가 있다.
통신 프로토콜처럼 이터레이션을 위한 프로토콜이 필요하다.
프로토콜에 따라 이터레이션 수행.
프로토콜이 구문과 빌트인이 아님. 프로토콜에 맞으면 이터레이션 가능.

3-1. 이터레이션 프로토콜

오브젝트가 이터레이션 할 수 있는 구조이어야 한다.
[10, 20]
이터레이션 함수를 갖고 있어야 한다.
var obj = list[Symbol.iterator]();
JavaScript
복사
이터레이션 프로토콜 구분
이터러블 프로토콜: 반복 가능해야 한다.
이터레이터 프로토콜: 반복 가능한 오브젝트를 이터레이터 오브젝트로 만드는 프로토콜
개발자 코드로 프로토콜을 맞추면 이터레이션 할 수 없는 오브젝트를 이터레이션 할 수 있도록 만들 수 있다.

3-2. 이터러블 오브젝트, 이터러블 프로토콜

이터러블 프로토콜이란?

오브젝트가 반복할 수 있는 구조이어야 하며 Symbol.iterator를 갖고 있어야 한다.
const arr = [ 1, 2, 3]; console.log(arr[Symbol.iterator]);
JavaScript
복사

이터러블 오브젝트

이터러블 프로토콜을 갖고 있는 오브젝트
반복 구조, Symbol.iterator()
자체 오브젝트에는 없지만 이터러블 오브젝트를 상속받아도 된다.
즉, prototype chain에 있으면 된다.
이터러블을 도입하면 다양한 데이터 구조(Array, Set, Map 등등)를 같은 방식으로 순회 가능.

3-3. 이터레이터 오브젝트, 이터레이터 프로토콜

이터레이터 프로토콜이란?

값을 순서대로 생성하는 방법

이터레이터 오브젝트

이터레이터 프로토콜을 갖고 있는 오브젝트. 이터레이터라고도 한다.
Symbol.iterator()를 호출하면 이터레이터 오브젝트를 생성하여 반환한다.
이터레이터 오브젝트에 next()가 있다.
이터레이터의 특징
next를 호출할 때마다 엘리먼트를 읽어들인다.
{ value: undefined, done: true }
→ 이터러블은 Symbol.iterator를 가지고 있어야 하고, 이터레이터는 next()를 호출해서 값을 하나씩 반환하는 객체이다.

4. Spread, Rest

4-1. Spread

[…iterable]
이터러블 오브젝트를 하나씩 전개(분리)
{ key: value }의 Object가 이터러블 오브젝트는 아니지만 전개 가능

Array spread

엘리먼트 단위로 전개된다.
const one = [1, 2]; const result = [10, 11, ...one] console.log(result) // [10, 11, 1, 2]
JavaScript
복사

String spread

const target = 'spread'; console.log([...target]) // [ 's', 'p', 'r', 'e', 'a', 'd' ]
JavaScript
복사

Object spread

이터러블 오브젝트가 아니므로 [ ] 에 작성할 수 없다.
const test = { food:'pizza', music:20} const result = {food:'burger', test1:40, ...test} console.log(result) // { food: 'pizza', test1: 40, music: 20 }
JavaScript
복사

4-2. Rest

호출하는 함수의 파라미터에 spread 대상 작성
함수가 호출되면 파라미터 배열을 엘리먼트 단위로 전개한다.
전개한 순서대로 파라미터 값을 넘겨줌.
호출받는 함수의 파라미터에 순서대로 맵핑된다.

rest 파라미터

function(param, paramN …name)
전개(분리)하여 받은 파라미터를 배열로 결합

유사배열(Array-like)

Object 타입이지만 이터러블 가능한 오브젝트
key 값이 0부터 1씩 증가해야 함.
length에 전체 프로퍼티 수를 작성해야 한다.
const values = { 0:'test1', 1:'test2', 2:'test3', length:3, }; for (let i = 0; i < values.length; i+=1){ console.log(values[i]); };
JavaScript
복사

rest와 arguments차이

argument 오브젝트
파라미터 작성에 관계없이 전체를 설정
Array-like 형태이다.
rest 파라미터
Array 오브젝트 형태

5. Destructing

구조 분해 할당
rest 파라미터는 호출받는 함수의 파라미터에 작성하지만, 나머지라는 시맨틱이 강해서 코드처럼 사용하기도 한다.

Array 분할 할당

let one, two, three, rest; [one, , three, ...rest] = [1,2,3,4,5]; console.log(one, three, rest) // 1 3 [4, 5]
JavaScript
복사

Object 분할 할당, 파라미터 분할 할당

구조를 맞춰주기 위한 변수는 실제로 존재하지 않는다.
const { one, test: { two, three }}}; = { one:10, test: { two: 20, three:30 }}} console.log(one, two, three); // 10 20 30 console.log(test); // ReferenceError
JavaScript
복사
const test = { one: 10, two: 20 }; function add({one, two}){ console.log(one + two); // 30 } add(test)
JavaScript
복사

6. Object Operation, default value

Object Operation

const A = 'A' const test = { [A+'1']: 100, [A+'2']: 200, [A+'3']: 300 } console.log(test) // { A1: 100, A2: 200, A3: 300 }
JavaScript
복사
const one= 10; const two = 20; const values = {one, two}; console.log(values);
JavaScript
복사
const value = { ["one" + "two"]: 12 }; console.log(value.onetwo); // 12
JavaScript
복사

default value

할당할 값이 없으면 디폴트 값을 할당
할당할 값이 있으면 디폴트 값을 무시
Object는 프로퍼티 이름으로 체크
const {one, two = 20} = {one: 10};
JavaScript
복사
디폴트 값 적용 순서는 왼쪽에서 오른쪽
const [one, two = one + 20, five = two + 50] = [10]; console.log(two, five) // 30 80
JavaScript
복사

7. for-of

이터러블 오브젝트를 반복
for-in의 경우는 열거 가능한 프로퍼티가 대상이다.
Object.defineProperty()는 디폴트가 enumerable: false
{ key: value } 형태는 디폴트가 enumerable: true
for-of
이터러블 오브젝트가 대상
Object는 전개되지 않는다.
prototype 프로퍼티도 전개되지 않음.

Object를 for-of로 전개할 수 있는 방법

Object.keys()로 프로퍼티 이름을 배열로 만들고 만든 배열을 for-of로 전개.
const test = {one:10, two: 20}; for (let key of Object.keys(test)){ console.log(key) }
JavaScript
복사

8. 연산자, getter, setter

생략

9. Number 오브젝트

Number.EPSILON

아주 작은 값
2522^{-52}
사용사례
console.log(0 / 0); // NaN console.log(0 / (0 + Number.EPSILON); // 0
JavaScript
복사

진수

2진수
0b0101, OB0101
8진수
0O0105

9-1. Number 함수

Number와 관련된 것은 Number 오브젝트의 함수를 사용한다. 글로벌 오브젝트의 함수는 글로벌 사용이 목적이다.
→ 글로벌 오브젝트 함수는 타입 변환이 일어난다.

isNaN()

NaN 값의 여부를 체크
console.log(Number.isNaN("ABC"), isNaN("DEF") // false true console.log(Number.isNaN("100"), isNaN("200") // true true
JavaScript
복사
글로벌 오브젝트의 isNaN()은 값 타입이 Number가 아닌 것을 체크한다.

isInteger()

파라미터 값이 정수이면 true
console.log(Number.isInteger(0)); // true console.log(Number.isInteger(1.0)); // true console.log(Number.isInteger(1.01)); // false console.log(Number.isInteger("12")); // false console.log(Number.isInteger(true)); // false
JavaScript
복사

isSafeInteger()

파라미터 값이 safe 정수이면 true.
(2531)-(2^{53}-1) ~ 2531 2^{53} -1

isFinite()

파라미터 값이 유한 값이면 true
글로벌 오브젝트의 isFinite()와 체크 결과가 다름
글로벌은 숫자로 변환한다.
console.log(Number.isFinite("70"), isFinite("80")); // false true
JavaScript
복사

10. String 오브젝트

10-1. unicode, ES5 호환성

unicode

U+0031 형태
코드 포인트
0031이 코드 포인트
문자코드라고도 부른다. 코드 포인트로 문자/이모지를 표현
plane
코드 포인트 전체를 17개 plane으로 나눈다.
하나의 plane은 65535개.(U+FFFF)
첫 번째 plane
BMP(Basic Multilingual Plane)라고 부름
일반적인 문자(한글, 영문자, 숫자)가 여기에 속함.
나머지 plane
5자리 이상의 코드 포인트를 표현할 수 있다.
이스케이프 시퀀스
역슬래시와 16진수로 값을 작성
console.log("\x31\x32\33"); // 123
JavaScript
복사
유니코드 이스케이프 시퀀스
console.log("\u0034\u0035\u0036"); // 456
JavaScript
복사
그런데 ES5에서는 U+FFFF보다 큰 코드 포인트를 작성할 수가 없었다. 따라서 Surrogate pair를 사용.

normalize()

대상 문자열을 파라미터에 지정한 유니코드 정규화 형식으로 변환하여 반환

10-2. 문자열 비교

startsWith()

대상 문자열이 첫 번째 파라미터의 문자열로 시작하면 true
두 번째 파라미터는 시작할 인덱스 지정
const target = "ABCDAB"; console.log(target.startsWith("AB")); // true console.log(target.startsWith("AB", 4)); // true
JavaScript
복사

endsWith()

대상 문자열이 첫 번째 파라미터의 문자열로 끝하면 true
두 번째 파라미터는 사용할 문자열 길이 지정
const target = "ABCDAB"; console.log(target.endsWith("AB")); // true console.log(target.endsWith("A", 4)); // true
JavaScript
복사

repeat()

파라미터에 작성한 수만큼 복제, 연결하여 반환

includes()

첫 번째 파라미터의 문자열 있으면 true
숫자이면 문자열로 변환하여 체크
두 번째 파라미터는 비교 시작 인덱스
startsWith(), endsWith(), repeat(), padStart(), padEnd(), trimStart(), trimEnd()와 같은 메소드들이 추가.

11. Object 오브젝트

생략

12. Array 오브젝트

from()

첫 번째 파라미터의 오브젝트를 Array 오브젝트로 변환
두 번째 파라미터에 함수 작성
이터러블 오브젝트를 전개할 때마다 호출
세 번째 파라미터에 오브젝트 작성
호출된 함수에서 this로 참조

of()

파라미터 값을 Array로 변환해서 반환

배열 엘리먼트 복사

copyWithin()

범위 값을 복사하여 같은 오브젝트에 설정
두 번째 파라미터 인덱스부터 복사하여

16. 제너레이터

function* 키워드를 사용한 함수
제너레이터 함수를 호출하면 함수 블록을 실행하지 않고 Generator 오브젝트를 생성하여 반환한다.

17. Symbol

생략

18. Map 오브젝트

key, value의 컬렉션
대괄호 안에 키와 값을 작성한다.
다양한 타입을 키로 사용할 수 있다.
sameValueZero 알고리즘을 사용한다.
const obj = new Map([ ["key","value"], [{book:200},"오브젝트"], [100,"number"] ]) console.log(obj) // Map(3) { 'key' => 'value', { book: 200 } => '오브젝트', 100 => 'number' }
JavaScript
복사

Map과 오브젝트 비교

빈번하게 key, value를 추가/삭제할 때는 Map이 Object보다 좋은 경우가 있다고 한다.
다양한 메소드를 지원하고 이터레이션도 할 수 있다. for-of 전개가 가능하다.
Obejct보다 확장성이 있고 유연하다.

19. WeakMap 오브젝트

weakMap은 object만 키로 사용할 수 있다.
number등 프리미티브 타입 사용이 불가하다.
Map에서 키로 참조한 object를 삭제하면 object를 사용할 수 없게 되지만, Map에 object가 남는다.
let sports = {like : "축구"}; const obj = new Map([ [sports, "like:축구"] ]); sports = {like:"농구"} console.log("🚀 ~ sports:", sports)
JavaScript
복사
→ 즉, WeakMap"객체가 삭제될 때 부가 데이터도 자동으로 삭제되는" 경우에 적합
let map = new Map(); let weakMap = new WeakMap(); let obj1 = { name: "Alice" }; let obj2 = { name: "Bob" }; map.set(obj1, "Developer"); map.set(obj2, "Designer"); weakMap.set(obj1, "Developer"); weakMap.set(obj2, "Designer"); // ✅ Map은 keys(), values(), entries() 사용 가능 console.log([...map.keys()]); // [{ name: "Alice" }, { name: "Bob" }] // ❌ WeakMap에서는 keys()를 사용할 수 없음 console.log([...weakMap.keys()]); // TypeError: weakMap.keys is not a function
JavaScript
복사

Map과 WeakMap 차이

참조하는 object를 삭제하면 Map은 그대로 갖고 있지만, WeakMap은 GC 처리로 삭제됨.