JavaScript : Syntactic sugar
1. 화살표 함수 (Arrow Fun
ctions)
전통적인 함수 선언 방식보다 간결하게 함수를 작성할 수 있게 해준다.
// 기존 함수 표현식
function add(a, b) {
return a + b;
}
// 화살표 함수
const add = (a, b) => a + b;
2. 템플릿 리터럴 (Template Literals)
택틱 ( `` )을 사용하여 문자열 내에 변수나 표현식을 쉽게 포함할 수 있다.
const name = "Alice";
console.log(`Hello, ${name}`);
3. 디스트럭처링 (Destructuring Assignment)
배열이나 객체에서 필요한 값들을 간단하게 추출할 수 있다.
// 객체 디스트럭처링
const person = { name: "Bob", age: 30 };
const { name, age } = person;
//배열 디스트럭처링
const arr = [1, 2, 3];
const [first, second] = arr;
4. 기본 매개변수 (Default Parameters)
함수의 매개변수에 기본ㄱ밧을 지정하여, 인자가 전달되지 않았을 때도 안정적인 동작을 보장한다.
function greet(name = "Guest") {
return `Hello, ${name}!`;
}
5. 스프레드 연산자 (Spread Operator)와 나머지 매개변수 ( Rest Parameters)
배열이나 객체를 확장하거나, 함수에 전달되는 인자들을 쉽게 다룰 수 있다.
// 스프레드 연산자
const arr = [1, 2, 3];
const newArr = [...arr, 4, 5];
// 나머지 매개변수
function sum(...numbers) {
return numbers.reduce((acc, cur) => acc + cur, 0);
}
6. 클래스 문법 (Class Syntax)
ES6부터 도입된 클래스 문법은 기존의 프로토타입 기반 상속을 더 직관적이고 객체지향적으로 표현할 수 있도록 도와준다. 실제로 클래스는 프로토타입 기반 상속 위에 얹은 문법적 설탕임.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, my name is ${this.name}`);
}
}
const bob = new Person("Bob", 30);
bob.greet();
7. 옵셔널 체이닝 ( Optional Chaining)과 널 병합 연산자 (Nullish Coalescing)
옵셔널 체이닝 (?.):
객체의 깊은 프로퍼티에 접근할 때, 해당 프로퍼티가 존재하지 않아도 에러를 발생시키지 않고 undefined를 반환.
const user = { profile: { name: "Charlie" } };
console.log(user.profile?.name); // "Charlie"
console.log(user.address?.city); // undefined
널 병합 연산자 (??):
값이 null 또는 undefined인 경우에만 우측의 기본값을 사용한다.
const input = null;
const value = input ?? "default value";
console.log(value); // "default value"
8. 객체 리터럴의 확장된 표현
객체 속성 축약 (Shorthand Property Names):
변수 이름과 객체의 속성 이름이 동일할 때, 중복 작성 없이 축약할 수 있다.
const x = 10;
const y = 20;
const point = { x, y }; // { x: 10, y: 20 }
객체 메서드 축약 (Method Definitions):
객체 내 함수를 정의할 때, function 키워드를 생략하고 메서드 이름만으로 작성할 수 있다.
const Person = {
name: "Alice",
greet() {
console.log(`Hello, my name is ${this.name}`);
}
};
person.greet();
계산된 속성명 (Computed Property Names):
대괄호( [] )를 사용하여 객체 리터럴 내에서 속성 이름을 동적으로 계산할 수 있다.
const prop = "age";
const user = {
name: "Bob",
[prop]: 30
};
console.log(user.age); // 30
객체 확산 및 나머지 프로퍼티 (Object Rest/Spread):
const obj = { a: 1, b: 2, c: 3 };
const { a, ...others } = obj; // others: { b: 2, c: 3 }
9. 비동기 프로그래밍의 간소화
Async/Await:
Promise 기반의 비동기 코드를 동기식 코드처럼 읽기 쉽게 작성할 수 있게 해준다.
async function fetchData() {
try {
const response = await fetch("https://api.example.com/data");
const data = await response.json();
return data;
} catch (error) {
console.log("Error fetching data:", error);
}
}
비록 내부적으로는 Promise를 사용하지만, 코드가 훨씬 간결해지고 예외 처리가 쉬워진다.
10. 지수 연산자 (Exponentiation Operator)
수학적인 지수 연산을 간결하게 표현할 수 있다.
const result = 2 ** 3; // 8
// 기존 방식: Math.pow(2, 3);
11. Tagged Template Literals
템플릿 리터럴 앞에 함수를 붙여 문자열 처리를 커스터마이징할수 있다.
function emphasize(strings, ...values) {
return strings.reduce(
(acc, str, i) => acc + str + (values[i] ? `<strong>${values[i]}</strong>` : ""),
""
);
}
const name = "Charlie";
const message = emphasize`Hello, ${name}! Welcome to our site.`;
console.log(message);
// "Hello, <strong>Charlie</strong>! Welcome to our site."
12. 모듈 시스템 (Import/Export)
ES6 모듈 문법은 코드를 모듈 단위로 관리하고 재사용하기 쉽게 만듭니다. 이는 전동적인 IIFE나 CommonJS 방식에 비해 훨씬 간결한 표현을 제공한다.
내보내기 (Export):
// math.js
export function add(a, b) {
return a + b;
}
가져오기 (Import):
// main.js
import { add } from './math.js';
console.log(add(2, 3));
13.for...of 루프
이터러블(iterable)한 객체를 순회할 때 사용되는 구문으로, 내부의 반복작(iterator)를 자동으로 호출해 준다.
const arr = [10, 20, 30];
for (const value of arr) {
console.log(value);
}
14. Generator 함수 (함수* 구문)
상태를 유지하면서 여러 번에 걸쳐 실행할 수 있는 함수로, 내부적으로 반복자 패턴을 간결하게 구현할 수 있도록 해준다.
function* count() {
yield 1;
yield 2;
yield 3;
}
const couter = count();
console.log(counter.next().value); // 1;
console.log(counter.next().value); // 2;
15. 논리 할당 연산자 (Logical Assignment Operators)
ES2021에서 도입된 이 연산자들은 기존의 논리 연산과 할당을 결합해 코드를 더욱 간결하게 만들어준다.
||= (논리 OR 할당):
피연산자가 falsy한 값일 때 우측 값을 할당한다.
let a = 0;
a ||= 10; // a가 falsy하므로, a는 10이 됨
&&= (논리 AND 할당):
피연산자가 truthy한 값일 때 우측 값을 할당한다.
let b = 5;
b &&= 20; // b가 truthy하므로, b는 20이 됨
??= (널 병합 할당): 위의 널 병합 연산자와는 다르다. ?? 는 널 병합 연산자 ??= 는 널 병합 할당이다.
피연산자가 null 또는 undefined일 때 우측 값을 할당한다.
let c = null;
c ??= 30; // c가 null이므로, c는 30이 됨
16. 선택적 Catch 바인딩 (Optional Catch Binding)
ES2019부터 catch 블록에서 에러 객체를 생략할 수 있게 되어, 에러 객체를 사용하지 않을 때 코드를 더 간결하게 작성할 수 있다.
try {
// 에러를 발생시킬 수 있는 코드
doSomething();
} catch {
// 에러 객체 받지 않음
console.log("에러가 발생했습니다.");
}
17. 동적 Import (Dynamic Imports)
모듈을 동적으로 불러올 수 있게 해 주는 구문으로, 정적 import와 달리 실행 시점에 모듈을 불러온기 때문에 조건에 따라 모듈을 로딩하거나 코드 분할에 유용하다.
import("./module.js")
.then(module => {
module.doSomething();
})
.catch(err => {
console.error("모듈 로딩 중 오류 발생:", err);
});
18. for-await-of 루프
비동기 이터러블 객체를 순회할 때 사용하는 구문으로, 비동기 처리를 동기식 코드처럼 작성할 수 있다.
async function processAsyncData(asyncIterable) {
for await (const data of asyncIterable) {
console.log(data);
}
}
19. Async Generator 함수
비동기 작업을 수행하면서도 여러 값을 순차적으로 yield할 수 있는 함수다. 일반 제너레이터와 async/await를 결합한 형태
async function* asyncGenerator() {
yield await Promise.resolve("첫번째 값");
yield await Promise.resolve("두번째 값");
}
(async () => {
for await (const value of asyncGeneration()) {
cosole.log(value);
}
})();
20. 클래스의 개인 필드와 메서드(Private Class Fields and Methods)
ES2022에서 도입된 기능으로, 클래스 내부에서만 접근 가능한 비공개 필드와 메서드를 # 기호를 사용해 정의할 수 있다. 이는 객체지향 프로그래밍에서 캡슐화를 강화해 준다.
class Example {
#privateField = 42; // 비공개 필드
#privateMethod() { // 비공개 메서드
return this.#privateField;
}
getPrivate() {
return this.#privateMethod();
}
}
const intance = new Example();
console.log(instance.getPrivate()); // 42
// intance.#privateField; // 오류 발생: 외부 접근 불가
21. 후행 쉼표 (Trailing Commas)
함수 매개변수, 배열, 객체 등에서 마지막 요소 뒤에 쉼표를 허용함으로써 코드의 변경 시 diff가 깔끔해지고, 여러 줄에 걸친 선 시 가독성을 높여준다.
function example(
a,
b, // 마지막 매개변수 뒤에도 쉼표를 사용할 수 있음
) {
//함수 내용
}
const arr = [
1,
2,
3, // 배열의 마지막 요소 뒤에도 쉼표를 허용
]
22. 함수 이름 추론 (Function Name Inference)
변수나 객체 속성에 할당된 익명 함수는 자동으로 이름이 추론되어 name 프로퍼티에 할당된다. 이로인해 디버깅 시 함수의 이름을 쉽게 확인할 수 있다.
const myFunc = funcion() {};
console.log(myFunc.name);o // "myFunc"
const obj = {
greet() {
console.log("Hello");
},
};
console.log(obj.greet.name); // "greet"