728x90
ES6이란?
- 자바스크립트 표준 사양인 ECMAScript의 6번째 버전
→ 기존 자바스크립트의 단점을 보완하고 코드 작성의 생산성과 가독성을 크게 향상시킨 표준 - ECMAScript 2015로 알려져 있으며 ES6으로 불림
- 2009년에 표준화된 ES5 이후 2015년에 자바스크립트의 대규모 업데이트가 이루어진 것이 ES6
- ECMAScript는 ES6이후 매년 새로운 버전을 발표하였으며 버전 이름은 발표 연도로 정해지지만, ES6 이후의 버전들은 ES6+로 불림
Ex) ES7(2016), ES8(2017), ES9(2018), ES10(2019), ES11(2020), ES12(2021), ES13(2022)
ES6 문법
const와 let
- ES6에서 새로 등장한 키워드
- const는 상수 선언이기 때문에 값의 재할당 불가능
→ Java의 final과 유사하지만 final은 변수 뿐만 아니라 클래스, 메서드에도 사용 되어 상속, 오버라이딩 제한 등 더 광범위한 의미를 가짐 - const는 HTML 요소를 선택할 때 사용하는 것은 매우 좋은 관례
→ 단, 참조 변경이 필요할 경우 let 사용
// ES5
var MyBtn = document.getElementById('mybtn');
// ES6
const MyBtn = document.getElementById('mybtn');
- let은 const와 달리 값의 재할당 가능
→ 즉, 변경 가능한 변수가 생성 됨 - 중복 선언이 불가하여 동일한 이름의 변수를 같은 스코프 내에서 재 선언 불가
let name = '철수';
name = '영희';
console.log(name);
// 출력 => 영희
let a = 10;
let a = 20; // SyntaxError: Identifier 'a' has already been declared
- var는 선언 위치와 상관 없이 스코프의 최상단으로 끌어올려지는 현상(호이스팅) 때문에 코드의 예측 가능성을 낮춤
- const와 let은 블록스코프를 가지며, 선언 이전에 사용할 경우 ReferenceError가 발생하여 var 보다 안전
호이스팅(hoisting) 이란?
- JavaScript 엔진이 실행 전에 변수와 함수 선언을 스코프의 최상단으로 끌어올리는 동작을 의미
- 이로 인해 코드에서 변수를 선언하기 전에 참조해도 오류가 발생하지 않는 상황이 발생할 수 있음
console.log(a); // undefined (호이스팅 발생)
var a = 10;
console.log(a); // 10
- 위의 코드는 JavaScript 엔진이 var를 호이스팅하여 아래와 같이 실행 됨
var a; // 선언만 끌어올림
console.log(a); // undefined
a = 10; // 할당은 원래 위치에서 수행
console.log(a); // 10
- 하지만, let과 const는 호이스팅 되더라도 TDZ(Temporal Dead Zone)에 걸려 선언 전에 접근 시 ReferenceError 발생
→ TDZ는 let과 const의 변수 선언 이전에 해당 변수를 참조하지 못하도록 보호하는 메커니즘
→ TDZ는 JavaScript 코드의 안정성과 예측 가능성을 높임
console.log(a); // ReferenceError
let a = 10;
화살표 함수 (Arrow Functions)
- 코드의 가독성을 높이고 this 바인딩 문제를 해결하는 데 유용
- 화살표 함수를 map과 filter, reduce 등 내장 함수와 함께 사용 가능
- Java의 람다 표현식과 유사
구문 간결화
// ES5
function myFunc(name) {
return '안녕' + name;
}
console.log(myFunc('영희')); // 안녕 영희
// ES6 화살표 함수
const myFunc = (name) => {
return `안녕 ${name}`;
}
console.log(myFunc('영희')); // 안녕 영희
// 중괄호와 return 또한 생략 가능
const myFunc = (name) => `안녕 ${name}`;
console.log(myFunc('영희')); // 안녕 영희
this 바인딩
- 화살표 함수는 자신만의 this를 가지지 않는 대신 선언된 위치의 this를 상속
- 일반 함수에서의 this는 호출되는 객체에 따라 달라지지만 화살표 함수는 이를 고정
const obj = {
value: 10,
regularFunction: function () {
console.log(this.value); // 10 (obj를 가리킴)
},
arrowFunction: () => {
console.log(this.value); // undefined (전역 `this`를 가리킴)
},
};
obj.regularFunction();
obj.arrowFunction();
익명 함수로 사용
- 화살표 함수는 항상 익명
- 함수 이름이 필요하지 않은 곳(콜백 함수 등)에서 자주 사용
// ES5
const myArrary = ['진수', '영철', '영희', 5];
let arr1 = myArrary.map(function(item) {
return item;
});
console.log(arr1); // 출력 => (4) ["진수", "영철", "영희", 5]
// ES6
let arr2 = myArrary.map((item) => item);
console.log(arr2); // 출력 => (4) ["진수", "영철", "영희", 5]
const numbers = [1, 2, 3];
const squares = numbers.map(num => num * num);
console.log(squares); // [1, 4, 9]
매개변수가 하나일 때 괄호 생략 가능
const square = x => x * x; // 매개변수가 하나라면 괄호 생략 가능
중괄호 사용 시 return 필요
- 여러 줄로 구성된 함수는 중괄호를 사용하고 명시적으로 return을 반드시 사용
const multiply = (a, b) => {
const result = a * b;
return result;
};
화살표 함수의 한계
this를 가지지 않음
- 객체 메서드로 사용할 때 화살표 함수는 적합하지 않음
const obj = {
value: 10,
method: () => console.log(this.value),
};
obj.method(); // undefined (this가 전역 객체를 가리킴)
arguments 객체를 가지지 않음
- 화살표 함수는 arguments 객체를 사용할 수 없는 대신, ...rest 문법을 사용
const func = (...args) => args;
console.log(func(1, 2, 3)); // [1, 2, 3]
생성자로 사용할 수 없음
- 화살표 함수는 new 키워드로 호출할 수 없음
const Person = (name) => {
this.name = name;
};
const john = new Person('John'); // TypeError: Person is not a constructor
템플릿 리터럴 (Template Literals)
- 기존 ES5에서 문자열과 변수를 연결하기 위해서는 작은 따옴표( ' ) 혹은 큰 따옴표( " )와 더하기 연산자(+)를 사용하여 표현
- ES6에서는 백틱(`)을 사용하여 더하기 연산자(+) 없이 더 간결하고 직관적으로 표현 가능
// ES5
const name = '철수';
const age = 25;
const message = '안녕하세요, 제 이름은 ' + name + '이고, 나이는 ' + age + '살입니다.';
console.log(message); // 안녕하세요, 제 이름은 철수이고, 나이는 25살입니다.
// ES6 템플릿 리터럴
const name = '철수';
const age = 25;
const message = `안녕하세요, 제 이름은 ${name}이고, 나이는 ${age}살입니다.`;
console.log(message); // 안녕하세요, 제 이름은 철수이고, 나이는 25살입니다.
- ${} 구문을 사용하여 문자열 안에 변수 삽입이 가능할 뿐만 아니라 표현식도 사용 가능
→ JSP의 EL 표현식( ${} )과 유사
const x = 10;
const y = 20;
console.log(`x + y = ${x + y}`); // 출력: x + y = 30
- 템플릿 리터럴을 사용하면 줄바꿈(\n) 없이도 여러 줄 문자열을 작성 가능
const multiline = `이것은
여러 줄로 작성된
문자열입니다.`;
console.log(multiline);
/* 출력:
이것은
여러 줄로 작성된
문자열입니다.
*/
- 템플릿 리터럴을 가공하기 위해 함수와 함께 사용 가능
function tag(strings, ...values) {
console.log(strings); // ["안녕하세요, 제 이름은 ", "이고, 나이는 ", "살입니다."]
console.log(values); // ["철수", 25]
return `${values[0]}님은 ${values[1]}살입니다.`;
}
const name = '철수';
const age = 25;
console.log(tag`안녕하세요, 제 이름은 ${name}이고, 나이는 ${age}살입니다.`); // 철수님은 25살입니다.
기본 매개 변수 (Default Parameters)
- 함수에서 특정 파라미터에 값이 전달되지 않은 경우 해당 파라미터에 대한 기본값을 사용하는 방식
- 함수 호출 시 매개변수를 명시적으로 전달하지 않아도 기본값을 사용해 예상치 못한 undefined 에러를 방지
- 기본 매개 변수의 동작
- 파라미터가 넘어오지 않았을 경우
- undefined가 넘어왔을 경우
단, null이 전달될 경우 기본값이 무시 되고 null 사용
// 기본 매개 변수를 사용하지 않은 경우
function greet(name) {
return `Hello, ${name}!`;
}
console.log(greet()); // Hello, undefined!
console.log(greet('철수')); // Hello, 철수!
// 기본 매개 변수를 사용하는 경우
function greet(name = '익명') {
return `Hello, ${name}!`;
}
console.log(greet()); // Hello, 익명!
console.log(greet('철수')); // Hello, 철수!
- 기본 매개 변수와 undefined
function greet(name = '익명') {
return `Hello, ${name}!`;
}
console.log(greet(undefined)); // Hello, 익명!
console.log(greet(null)); // Hello, null!
- 동적 기본값 설정
- 두 번째 매개 변수 b의 기본값이 첫 번째 매개 변수 a를 활용
function sum(a = 0, b = a * 2) {
return a + b;
}
console.log(sum()); // 0 (a = 0, b = 0 * 2)
console.log(sum(5)); // 15 (a = 5, b = 5 * 2)
console.log(sum(5, 10)); // 15 (a = 5, b = 10)
배열 및 객체의 비구조화 (Array and Object destructing)
- 배열이나 객체의 속성을 간단하고 가독성 좋게 변수로 추출하는 방법
- 기존의 ES5 방식보다 훨씬 간결하고 효율적인 코드를 작성 가능
비구조화 할당
// 객체의 비구조화 할당 : 중괄호 사용
// ES5
const person = {
name: '철수',
age: 25,
city: '서울'
};
const name = person.name;
const age = person.age;
const city = person.city;
console.log(name, age, city); // 철수 25 서울
// ES6
const person = {
name: '철수',
age: 25,
city: '서울'
};
const { name, age, city } = person;
console.log(name, age, city); // 철수 25 서울
// 배열의 비구조화 할당 : 대괄호 사용
// ES5
const colors = ['red', 'green', 'blue'];
const first = colors[0];
const second = colors[1];
const third = colors[2];
console.log(first, second, third); // red green blue
// ES6
const colors = ['red', 'green', 'blue'];
const [first, second, third] = colors;
console.log(first, second, third); // red green blue
기본값 설정
// 객체의 기본값
const person = { name: '철수', city: '서울' };
const { name, age = 20, city } = person;
console.log(name, age, city); // 철수 20 서울
// 배열의 기본값
const colors = ['red', 'green'];
const [first, second, third = 'blue'] = colors;
console.log(first, second, third); // red green blue
중첩 구조의 비구조화
// 객체의 중첩 구조
// ES5
var person = {
name: '철수',
address: {
city: '서울',
zip: '12345'
}
};
// 중첩된 속성에 직접 접근
var name = person.name;
var city = person.address.city;
var zip = person.address.zip;
console.log(name); // 철수
console.log(city); // 서울
console.log(zip); // 12345
// ES6
const person = {
name: '철수',
address: {
city: '서울',
zip: '12345'
}
};
const { name, address: { city, zip } } = person;
console.log(name, city, zip); // 철수 서울 12345
// 배열의 중첩 구조
// ES5
var colors = [
['red', 'green'],
['blue', 'yellow']
];
// 중첩된 배열의 요소에 인덱스를 이용해 접근
var first = colors[0][0];
var second = colors[0][1];
var third = colors[1][0];
var fourth = colors[1][1];
console.log(first); // red
console.log(second); // green
console.log(third); // blue
console.log(fourth); // yellow
// ES6
const colors = [
['red', 'green'],
['blue', 'yellow']
];
const [ [first, second], [third, fourth] ] = colors;
console.log(first, second, third, fourth); // red green blue yellow
Rest 패턴
- 나머지 값을 별도로 추출할 때도 유용
// 객체의 Rest 패턴
const person = {
name: '철수',
age: 25,
city: '서울'
};
const { name, ...rest } = person;
console.log(name); // 철수
console.log(rest); // { age: 25, city: '서울' }
// 배열의 Rest 패턴
const colors = ['red', 'green', 'blue', 'yellow'];
const [first, ...rest] = colors;
console.log(first); // red
console.log(rest); // ['green', 'blue', 'yellow']
객체의 비구조화 할당 주의 사항
- 객체의 속성명과 동일한 이름의 변수가 아니라면 undefined 반환
- 반드시 속성의 이름과 동일하게 할당을 해야하며, 변수의 이름을 변경하려면 콜론( : )을 사용하여 변경 가능
// 속성명과 다를 경우 undefined
const person = {
name: '철수',
age: 25,
city: '서울'
};
let { username, age, city } = person;
console.log(username, age, city); // undefined 25 서울
// 콜론을 사용하여 변수명 변경
const person = {
name: '철수',
age: 25,
city: '서울'
};
let { name : username, age, city } = person;
console.log(username, age, city); // '철수' 25 '서울'
가져오기 및 내보내기 (Import and Export)
- 모듈(module) 기능을 제공하는 ES6의 핵심 개념
- JavaScript 코드의 재사용성과 관리성을 높이는 데 매우 유용
export
- 다른 파일에서 사용할 수 있도록 함수, 변수, 클래스 등을 내보내는 역할
- 두 가지 방식으로 사용
Named Export
- 하나의 모듈에서 여러 개를 내보낼 수 있음
- 각 항목은 고유한 이름 가져야 함
// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export const multiply = (a, b) => a * b;
export const divide = (a, b) => a / b;
Default Export
- 모듈에서 하나의 기본 값만 내보낼 때 사용
- export default는 이름 없이 내보낼 수 있음
// greet.js
export default function greet(name) {
return `Hello, ${name}!`;
}
import
- 다른 파일에서 내보낸 값을 가져오는 역할
- 내보낸 방식에 따라 가져오는 방법이 다름
Named Import
- 중괄호 {}를 사용해 원하는 항목을 가져옴
- 이름이 정확히 일치해야 함
// main.js
import { add, subtract } from './math.js';
console.log(add(10, 5)); // 15
console.log(subtract(10, 5)); // 5
Default Import
- 이름을 자유롭게 지정해서 가져올 수 있음
- 중괄호 {} 없이 가져옴
// main.js
import greet from './greet.js';
console.log(greet('철수')); // Hello, 철수!
Named Import와 Default Import를 함께 사용
// utils.js
export const format = (text) => text.toUpperCase();
export default function log(message) {
console.log(message);
}
// main.js
import log, { format } from './utils.js';
log(format('hello world')); // HELLO WORLD
Import All (*)
- 모든 Named Export를 하나의 객체로 가져올 수 있음
// main.js
import * as math from './math.js';
console.log(math.add(10, 5)); // 15
console.log(math.multiply(10, 5)); // 50
모듈 경로
- 상대 경로 : ./ 또는 ../로 시작 (./math.js)
- 절대 경로 : node_modules 또는 프로젝트의 설정에 따라 경로 지정 가능 (lodash)
프로미스(Promiss)
- ES6에서 추가된 비동기 코드를 사용하는 방식
- 이에 대해서는 콜백 함수, 프로미스, async/await에 대해 정리해둔 링크를 참조
나머지 매개 변수 및 확산 연산자(Rest parameter and Spread operator)
- 배열을 더 유연하고 간결하게 다룰 수 있도록 도와줌
나머지 매개변수 (Rest Parameter)
- 함수의 매개변수로 전달된 나머지 값을 배열 형태로 받는 문법
- ...을 사용하여 나머지 값을 하나의 배열로 처리
- 함수의 매개변수 목록에서 마지막에 위치
function introduce(name, age, ...hobbies) {
console.log(`이름: ${name}, 나이: ${age}`);
console.log(`취미: ${hobbies.join(', ')}`);
}
introduce('철수', 25, '축구', '음악', '영화 감상');
// 출력:
// 이름: 철수, 나이: 25
// 취미: 축구, 음악, 영화 감상
- 전달된 인자의 개수를 알 수 없을 때 유용
function sum(...numbers) {
return numbers.reduce((acc, curr) => acc + curr, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
확산 연산자 (Spread Operator)
- 확산 연산자는 배열을 개별 요소로 분리하거나, 복사 및 결합하는 데 사용
- ...을 사용하며, 배열, 함수 호출 등 여러 상황에서 활용
// 배열 복사
const arr1 = [1, 2, 3];
const arr2 = [...arr1]; // arr1의 복사본 생성
console.log(arr2); // [1, 2, 3]
// 배열 결합
const arr1 = [1, 2];
const arr2 = [3, 4];
const combined = [...arr1, ...arr2];
console.log(combined); // [1, 2, 3, 4]
// 함수 호출
const numbers = [10, 20, 30];
console.log(Math.max(...numbers)); // 30
차이점
특징 | 나머지 매개 변수(Rest) | 확산 연산자(Spread) |
역할 | 나머지 값을 배열로 수집 | 배열을 개별 요소로 분리 |
주요 사용처 | 함수의 매개 변수 | 배열, 함수 호출 등 |
문법 위치 | 함수 정의 시 ...변수명 | 배열, 함수 호출 앞 ... |
클래스(Classes)
- 객체를 생성하기 위한 템플릿 역할
- 이전에는 생성자 함수와 프로토타입을 사용하여 객체를 생성하고 상속을 구현했으나, ES6에서 클래스 문법이 도입되면서 더 간결하고 직관적인 방식으로 객체 지향 프로그래밍이 가능해짐
class Person {
// 생성자 함수 (객체 초기화)
constructor(name, age) {
this.name = name;
this.age = age;
}
// 메서드 정의
greet() {
console.log(`안녕하세요, 저는 ${this.name}이고, ${this.age}살입니다.`);
}
}
const person1 = new Person('철수', 25);
person1.greet(); // 안녕하세요, 저는 철수이고, 25살입니다.
클래스의 주요 특징
생성자(Constructor)
- 클래스에서 객체를 초기화하기 위해 사용하는 메서드
- 클래스 안에 한 번만 정의 가능
- 객체가 생성될 때 자동으로 호출
class Car {
constructor(brand, model) {
this.brand = brand;
this.model = model;
}
}
const myCar = new Car('Hyundai', 'Sonata');
console.log(myCar);
메서드 (Method)
- 클래스 안에서 정의된 함수
- 생성된 객체를 통해 호출 가능
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name}가 소리를 냅니다.`);
}
}
const dog = new Animal('강아지');
dog.speak(); // 강아지가 소리를 냅니다.
정적 메서드 (Static Method)
- 클래스 자체에서 호출할 수 있는 메서드
- 객체가 아니라 클래스 이름으로 호출
- static 키워드로 선언
class MathUtil {
static add(a, b) {
return a + b;
}
}
console.log(MathUtil.add(5, 3)); // 8
상속 (Inheritance)
- extends 키워드를 사용하여 클래스를 확장 가능
- 부모 클래스의 속성과 메서드를 자식 클래스에서 사용 가능
- super를 사용하여 부모 클래스의 생성자나 메서드를 호출 가능
class Vehicle {
constructor(type) {
this.type = type;
}
describe() {
console.log(`이것은 ${this.type}입니다.`);
}
}
class Bike extends Vehicle {
constructor(type, brand) {
super(type); // 부모 클래스의 생성자 호출
this.brand = brand;
}
showBrand() {
console.log(`브랜드: ${this.brand}`);
}
}
const myBike = new Bike('자전거', '삼천리');
myBike.describe(); // 이것은 자전거입니다.
myBike.showBrand(); // 브랜드: 삼천리
클래스와 객체 리터럴의 차이
특징 | 클래스 (Class) | 객체 리터럴 (Object Literal) |
생성 방식 | new 키워드를 사용해 인스턴스 생성 | 중괄호 {}로 생성 |
메서드 정의 | 클래스 내부에 정의 | 객체에 직접 정의 |
상속 | extends와 super로 구현 | Object.create() 또는 프로토타입 사용 |
참고 자료
[JavaScript] 자주 사용하는 ES6 문법 정리
들어가기 전에 Node.js와 React관련 프로젝트를 진행하면서 기존에 배워왔던 jQuery를 활용한 ES5 문법으로 JavaScript 코드를 작성하였지만 이제는 최신 트렌드에 맞게 ES6 문법으로 JavaScript 코드를 작성
velog.io
728x90
'Language > Javascript' 카테고리의 다른 글
[ES6+] ES7 ~ ES13 추가 기능 (1) | 2024.12.26 |
---|---|
[Javascript] DOM 렌더링 시점 (1) | 2024.12.09 |
[Javascript] DOM (Document Object Model)의 개념 (0) | 2024.12.09 |
[Javascript] 비동기 프로그래밍 [Callback, Promise, async/await] (0) | 2024.12.09 |
[Javascript] Javascript 동작 원리 [동기, 비동기] (0) | 2024.12.06 |