ECMAScript 2015는 JavaScript의 두 번째 주요 개정판입니다.
let은 블록 스코프 변수를 선언하는 키워드로, 변수를 블록 내에서만 유효하게 만듭니다. 블록 스코프를 가지기 때문에 전역 변수의 오버라이딩 문제를 방지하고 코드의 안정성을 높입니다.
const example = () => {
if (true) {
let x = 10;
console.log(x); // 10
}
// console.log(x); // 에러! x는 블록 스코프 내에서만 유효
};
const는 블록 스코프에서 읽기 전용 상수를 선언하는 키워드로, 한 번 할당되면 값을 변경할 수 없습니다.
const PI = 3.14;
// PI = 3.14159; // 에러! 상수를 변경할 수 없음
화살표 함수는 간결한 문법을 가진 익명 함수로, function 키워드 대신 =>를 사용하여 함수를 정의합니다. 매우 간결하고 가독성이 좋으며, this의 동작이 기존 함수 표현식과 다릅니다.
// 기존 함수 표현식
const add = function (a, b) {
return a + b;
};
// 화살표 함수
const addArrow = (a, b) => a + b;
구조분해할당은 배열이나 객체에서 원하는 값 또는 속성을 추출하여 변수에 할당하는 문법입니다. 이를 통해 코드의 가독성을 높일 수 있고, 필요한 값에 쉽게 접근할 수 있습니다.
// 배열 구조분해
const numbers = [1, 2, 3];
const [first, second, third] = numbers;
// 객체 구조분해
const person = { name: 'John', age: 30 };
const { name, age } = person;
전개 연산자(...)는 배열이나 객체 등을 펼쳐서 각각의 요소로 분리시키거나 합칠 때 사용합니다. Rest는 값을 수집하고, Spread는 값을 전개합니다.
≫ Rest Operator (...): Rest 연산자는 함수의 매개변수나 배열, 객체에서 사용되어 남은 인수들을 모아서 하나의 변수로 전달하거나, 배열/객체를 합칠 때 사용됩니다.
// 함수 매개변수에서의 활용
const sum = (...numbers) => numbers.reduce((acc, num) => acc + num, 0);
console.log(sum(1, 2, 3, 4)); // 10
// 배열에서의 활용
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combinedArray = [...arr1, ...arr2];
console.log(combinedArray); // [1, 2, 3, 4, 5, 6]
≫ Spread Operator (...): Spread 연산자는 배열이나 객체를 개별 요소로 분리하여 전개하거나 복사할 때 사용됩니다.
// 배열에서의 활용
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5];
console.log(arr2); // [1, 2, 3, 4, 5]
// 객체에서의 활용
const person = { name: 'John', age: 30 };
const copiedPerson = { ...person, job: 'Developer' };
console.log(copiedPerson);
// { name: 'John', age: 30, job: 'Developer' }
// 함수 호출에서의 활용
const displayInfo = (name, age) => console.log(`Name: ${name}, Age: ${age}`);
const user = ['Alice', 25];
displayInfo(...user); // Name: Alice, Age: 25
spread operator를 object로 쓸 때 단점
const original = { key: { nestedKey: 'value' } };
const copy = { ...original };
console.log(copy.key === original.key); // true
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function () {
console.log(`Hello, ${this.name}!`);
};
const john = new Person('John');
const copiedJohn = { ...john };
console.log(copiedJohn.sayHello); // undefined
const obj = { key: 'value' };
Object.defineProperty(obj, 'nonEnumerableKey', {
value: 'nonEnumerableValue',
enumerable: false,
});
const copiedObj = { ...obj };
console.log(copiedObj.nonEnumerableKey); // undefined
const obj = { [Symbol('key')]: 'value' };
const copiedObj = { ...obj };
console.log(copiedObj[Symbol('key')]); // undefined
Promise는 비동기 작업의 완료 또는 실패를 나타내는 객체로, 비동기 코드를 더 효과적으로 다룰 수 있게 합니다.
const fetchData = () => {
return new Promise((resolve, reject) => {
// 비동기 작업 수행
if (success) {
resolve(data);
} else {
reject(error);
}
});
};
fetchData()
.then(data => console.log(data))
.catch(error => console.error(error));
// then()은 성공 시 실행되며, catch()는 실패 시 실행됩니다.
for/of 루프는 이터러블 객체를 순회할 때 사용되며, 간편하게 배열이나 문자열의 값을 가져올 수 있습니다. 이터러블 컬렉션 객체 전용입니다.
const arr = [1, 2, 3];
for (const value of arr) {
console.log(value); // 1, 2, 3
}
const obj = { a: 1, b: 2, c: 3 };
for (let key in obj) {
console.log(key, obj[key]); // a 1, b 2, c 3
}
const fruits = ["Apple", "Banana", "Orange"];
fruits.forEach((fruit, index) => {
console.log(index, fruit); // 0 "Apple", 1 "Banana", 2 "Orange"
});
Map은 키-값 쌍을 저장하는 자료구조로, 객체보다 유연하게 다양한 데이터 타입을 키로 사용할 수 있습니다.
const myMap = new Map();
myMap.set('name', 'John');
myMap.set(1, 'One');
Set은 중복을 허용하지 않는 값들의 집합을 나타내는 자료구조로, 고유한 값만을 포함합니다.
const mySet = new Set([1, 2, 3, 1, 2]);
// mySet: {1, 2, 3}
클래스는 객체지향 프로그래밍을 지원하는데 사용되며, 생성자, 메서드, 상속 등을 정의할 수 있습니다.
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
console.log(`Hello, ${this.name}!`);
}
}
const person = new Person('Alice');
person.sayHello(); // Hello, Alice!
Symbol은 유일한 식별자를 생성하기 위한 원시 데이터 타입으로, 주로 객체 속성의 키로 사용됩니다.
const mySymbol = Symbol('description');
const obj = {
[mySymbol]: 'This is a symbol key'
};
const person = {
firstName: "John",
lastName: "Doe",
age: 50,
eyeColor: "blue"
};
let id = Symbol('id');
person[id] = 140353;
// Now person[id] = 140353
// but person.id is still undefined
함수의 매개변수에 기본 값을 설정할 수 있는 기능으로, 매개변수가 전달되지 않으면 기본값이 사용됩니다.
const greet = (name = 'Guest') => console.log(`Hello, ${name}!`);
greet(); // Hello, Guest!
문자열에 특정 문자열이 포함되어 있는지를 확인하는 메서드입니다.
⇨ includes(searchElement, fromIndex)
// searchElement: 찾을 값.
// fromIndex: 검색을 시작할 0 기반 인덱스, 정수로 변환.
const str = 'Hello, World!';
console.log(str.includes('World')); // true
// fromIndex < -array.length 이거나 fromIndex가 생략되면, 0이 사용되어 전체 배열이 검색됨.
// fromIndex >= array.length 이면, 배열은 검색되지 않고 false가 반환됨.
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
// 음수 인덱스는 배열의 끝부터 거꾸로 셈. 즉, fromIndex < 0이면, fromIndex + array.length가 사용.
[1, 2, NaN].includes(NaN); // true
["1", "2", "3"].includes(3); // false
문자열이 특정 문자열로 시작하는지를 확인하는 메서드입니다.
const str = 'Hello, World!';
console.log(str.startsWith('Hello')); // true
문자열이 특정 문자열로 끝나는지를 확인하는 메서드입니다.
const str = 'Hello, World!';
console.log(str.endsWith('World!')); // true
유사 배열 객체나 이터러블 객체를 배열로 변환하는 메서드입니다.
const arrayLike = { 0: 'a', 1: 'b', length: 2 };
const arr = Array.from(arrayLike); // ['a', 'b']
Array.from("ABCDEFG") // Returns [A,B,C,D,E,F,G]
배열의 각 인덱스를 가지고 있는 이터레이터 객체를 반환합니다.
const arr = ['a', 'b', 'c'];
const keys = arr.keys(); // 이터레이터 객체
let text = " ";
for(let x of keys) {
text += x + ","
}
// 0,1,2,
주어진 콜백 함수의 조건을 만족하는 첫 번째 요소를 반환합니다.
const numbers = [1, 2, 3, 4, 5];
const result = numbers.find(num => num > 2); // 3
주어진 콜백 함수의 조건을 만족하는 첫 번째 요소의 인덱스를 반환합니다.
const numbers = [1, 2, 3, 4, 5];
const index = numbers.findIndex(num => num > 2); // 2
ES6에서는 수학 연산을 위한 새로운 메서드들이 Math 객체에 추가되었습니다.
console.log(Math.trunc(3.5)) // 소수점 아래 없앰 ∴ 3, Math.trunc(-2.7) → -2
console.log(Math.sign(-8)) // 음수, 0, 양수 구분 ∴ -1, Math.sign(0) → 0, Math.sign(4) → 1
console.log(Math.pow(2, 3)) // 제곱 ∴ 8
console.log(Math.sqrt(9)) // 루트2 ∴ 3
console.log(Math.cbrt(64)) // 루트3 ∴ 4
console.log(Math.log2(2)) // 로그2 ∴ 1
console.log(Math.log10(10)) // 로그10 ∴ 1
Number 객체에는 새로운 프로퍼티들이 추가되었으며, 예를 들어 Number.EPSILON은 부동 소수점 연산에서 사용되는 가장 작은 양수를 나타냅니다.
console.log(Number.EPSILON); // 2.220446049250313e-16
console.log(Number.MIN_SAFE_INTEGER;); // -9007199254740991
console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
Number 객체에는 새로운 메서드들도 추가되었습니다.
console.log(Number.isInteger(5)); // true
console.log(Number.isSafeInteger(12345678901234567890)); // false
전역 객체에 추가된 새로운 메서드들로, 예를 들어 isFinite()이나 isNaN() 등이 있습니다.
isFinite(10/0); // (Infinity) returns false
isFinite(10/1); // returns true
isNaN("Hello"); // returns true
isNaN(5.0) = isNaN(5.) // returns false
entries() 메서드는 배열의 각 요소들을 [index, value] 형태의 배열로 변환하여, 이 배열들을 모아놓은 배열을 반환합니다. 하지만, 이 메서드는 바로 배열로 반환하지 않고, 이터러블한 객체를 반환합니다. 이를 배열로 바꾸려면 Array.from()이나 for...of 루프를 이용해야 합니다.
const fruits = ["Banana", "Orange", "Apple", "Mango"];
const f = fruits.entries();
Array.from(fruits.entries())
// [[0, 'Banana'], [1, 'Orange'], [2, 'Apple'], [3, 'Mango']]
// Object.entries() 메서드는 객체의 키-값 쌍을 배열로 반환합니다.
const person = { name: 'John', age: 30, job: 'Developer' };
const entries = Object.entries(person);
console.log(entries);
// [['name', 'John'], ['age', 30], ['job', 'Developer']]
모듈은 코드를 여러 파일로 나누고 재사용할 수 있도록 하는 기능으로, import와 export 키워드를 사용하여 모듈 간의 의존성을 정의합니다.
// math.js
export const add = (a, b) => a + b;
// main.js
import { add } from './math';
console.log(add(2, 3)); // 5
폴리필(Polyfill)
- 폴리필은 기본적으로 지원하지 않는 이전 브라우저에서 최신 기능을 제공하는 데 필요한 코드 (일반적으로 웹의 JavaScript)
- 바벨은 최신 ES6+ 문법을 ES5로 바꾸어주는 것(컴파일)이고, polyfill은 브라우저가 이해할 수 없는 코드에 대하여, 이해할 수 있는 코드 소스를 제공하는 것.
- ES5의 global namespace(window)에 존재하지 않는 것은 컴파일 하지 못하여, 폴리필이 필요함.
- 컴파일 가능 - 새로운 “문법"인 경우
- const, let
- spread operator
- arrow function
- class
- destructuring
- 컴파일 불가 - 폴리필 필요
- 새로운 객체 (Promise, IntersectionObserver, Set, Map …)
- 기존 객체의 새로운 메서드 (Array.prototype.includes, Object.entries …)
- 새로운 함수 (fetch)
이터러블(Iterable), 이터레이터(Iterator)
JavaScript에서 데이터를 순회하는 데 사용되는 개념입니다.
- 이터러블: 반복 가능한 객체로, Symbol.iterator 메서드를 가지고 있습니다. 이 메서드는 이터레이터를 반환하며, 이터레이터는 next() 메서드를 갖고 있습니다.
ex) 배열이나 문자열과 같은 데이터 구조.- 이터레이터: 이터러블 객체의 각 요소를 순차적으로 접근할 수 있게 해주는 객체입니다. 이터레이터는 next() 메서드를 갖고 있으며, 각 호출마다 { value, done } 형태의 결과를 반환합니다.
const iterableArray = [1, 2, 3]; const iterator = iterableArray[Symbol.iterator](); console.log(iterator.next()); // { value: 1, done: false } console.log(iterator.next()); // { value: 2, done: false } console.log(iterator.next()); // { value: 3, done: false } console.log(iterator.next()); // { value: undefined, done: true }
Object의 key에 공백이 있을 경우 접근하는 방법
const myObject = { "hello heonje" : "hi" } const keyAsVariable = "hello heonje" myObject.helloWorld = "earth" --- console.log(myObject.hello_heonje) // undefined console.log(myObject["hello heonje"]) // hi console.log(myObject.keyAsvariable) // undefined console.log(myObject[keyAsVariable]) // hi console.log(myObject.helloWorld) // earth console.log(myObject[helloWorld]) // earth