[JavaScript] ES6 문법 정리

COCOBALL·2024년 1월 2일

JavaScript

목록 보기
2/2
post-thumbnail

var, let and const

  • var: 재정의와 재선언 모두 가능
  • let: 가변변수로 재정의가 가능하지만 재선언은 불가능
  • const: 불변변수로 재선언과 재정의 모두 불가능

재선언: 똑같은 이름의 변수를 다시 만드는 것

재정의: 값이 지정된 변수에 값을 바꾸려는 것

스코프(scope): 식별자(ex. 변수명, 함수명, 클래스명 등)의 유효범위

var

// 변수 선언
var x = 2;

// 재정의
x = 4;

// 재선언
var x = 4;

var의 문제점
1. 변수 선언이 유연하기 때문에 예기치 못한 값을 반환할 가능성이 있음
2. 코드가 길어진다면 어디에서 어떻게 사용될 지 파악하기 힘듦
3. 함수 레벨 스코프로 인해 함수 외부에서 선언한 변수는 모두 전역 변수
4. 변수 선언문 이전에 변수를 참조하면 언제나 undefined를 반환 (hoisting 발생)

→ 따라서, var는 잘 사용하지 않으며, letconst 키워드를 사용하는 것을 권장

  • let: 블록 범위 변수를 선언하는데 사용하며 블록 범위 변수는 해당 변수가 선언된 중괄호 블록 내에서만 유효
let x = 10;
if (true) {
	let x = 20;
	console.log(x);
}
console.log(x);
  • const: 상수(constant)를 선언하는 데 사용하며 상수는 초기 값이 할당된 후에는 변경할 수 없는 변수, 한 번 할당된 값은 재할당 불가능
const PI = 3.14;
console.log(PI);  // 3.14

PI = 3.14159; // Error: 상수에 재할당할 수 없음

const로 선언된 객체와 배열은 참조를 변경하지 못하지만, 객체나 배열 내부의 속성과 요소는 수정 가능

const person = {
	name: 'John',
	age: 30
};

person.age = 31;
person = {}; // Error: 상수에 재할당할 수 없음

const number = [1, 2, 3];
number.push(4);
number = []; // Error: 상수에 재할당할 수 없음

let과 const의 차이점

let은 변수를 선언하며, 재할당이 가능. 반면에 const는 상수를 선언하며, 재할당이 불가능

let으로 선언된 변수는 초기화되지 않은 상태로 선언할 수 있지만, const는 선언과 동시에 반드시 초기값을 할당해야 함.

letconst는 모두 블럭 범위이기 때문에 변수는 범위 내에서만 사용 가능

Template literals

  • 문자열 생성 시 따옴표 대신, 백틱(`)을 사용
  • 따옴표와 달리 백틱 안에서는 줄바꿈이 반영
  • 문자열 사이에 변수나 연산을 넣을 때는 ${} 사이에 표현식을 삽입
// 기존 코드 방식
function myFunc1(){
	return '안녕' + name + '너의 나이는' + age + '살 이다!';
}

console.log('영희', 22);
// 출력 결과 => 안녕 영희 너의 나이는 22살 이다!

// 템플릿 리터럴 방식
const myFunc = (name, age) => {
	return `안녕 ${name}, 너의 나이는 ${age}살 이다!`;
};

console.log(myFunc('영희', 22)); 
// 출력 결과 -> 안녕 영희, 너의 나이는 22살 이다!

Arrow functions

화살표 함수는 함수 표현식을 보다 단순하고 간결하게 작성하는 문법

// 기존 방식
const myFunc(name){
	return `안녕 ${name}`;
}

console.log(myFunc('영희'));  // 출력 => 안녕 영희
// 화살표 함수 방식
const myFunc = (name) => {
	return `안녕 ${name}`;
}

console.log(myFunc('영희'));  // 출력 => 안녕 영희

// 또는 화살표를 사용하거나 'return' 키워드를 사용하지 않아도 됨
const myFunc = (name) => `안녕 ${name}`;

console.log(myFunc('영희'));  // 출력 => 안녕 영희

const myFunc2 = (a, b) => a+b;
arr.map((el) => el*2);
// ES5 방식
const myArray = ['진수', '영철', '영희', '5'];

let arr1 = myArray.map(function(item){
	return item;
});

console.log(arr1);

// ES6 방식
let arr2 = myArray.map((item) => item);

console.log(arr2);
  • 인수가 하나밖에 없다면 인수를 감싸는 괄호를 생략할 수 있음
  • 인수가 하나도 없을 땐 괄호를 비워놓으면 된다. 다만, 이 때 괄호를 생략 불가능
  • 본문이 한 줄 밖에 없다면 중괄호를 생략 가능
  • 중괄호는 본문 여러 줄로 구성되어 있음을 알려주며, 중괄호를 사용했다면 return으로 결과값을 반환해줌

import and export

모듈을 내보내는 방법으로는 named exportdefault export(= import)가 있음

// named export 기본 형식
export {모듈명1, 모듈명2};
import {모듈명1, 모듈명2} from 'js 파일 경로';

// default export 기본 형식
export default 모듈명;
import 모듈명 from 'js 파일 경로';

named export

  • 한 파일에서 여러 개를 export할 때 사용 가능
  • export한 이름과 동일한 이름으로 import해야 하며, 중괄호에 묶어서 import 해야 한다.
  • 다른 이름으로 import 하려면 as를 사용하고, 한 파일에 있는 클래스나 변수들을 한 번에 import 하려면 * as 를 사용한다.
// named export는 중괄호 포함 import
import {named1, named2} from './example.js';

// named export에서 as를 사용하여 다른 이름으로 import
import {named1 as myExport, named2} from './example.js';

// 한 파일에 있는 모든 클래스나 변수를 * as를 사용하여 한 번에 import
import * as Hello from './example.js';

default export

  • 하나의 파일에서 단 하나의 변수 또는 클래스 등만 export 가능
  • import 할 때 아무 이름으로나 자유롭게 import 가능하며, 중괄호에 묶지 않아도 된다.
// default export는 중괄호 없이 import
import default1 from './example.js';

일반적으로 js 파일을 불러오고 하다보면, 통으로 가져오는 부분이 크다보니 성능이나 시간에 차이가 생기기 마련이지만 export를 사용하면 선택적으로 다른 JavaScript 구성 요소에 사용할 function을 내보낼 수 있음

다른 컴포넌트에 사용하기 위해 가져오기 import를 사용

Class

class는 객체를 생성하기 위한 템플릿으로, 틀과 같은 역할을 함

  • 클래스를 선언하려면 class 키워드와 함께 클래스의 이름을 작성
  • 클래스는 함수로 호출 불가능
  • 클래스 선언은 letconst처럼 블록 스코프에 선언되며, 호이스팅(hoisting)이 일어나지 않음

클래스는 반드시 정의한 뒤에 사용한다.

  • 클래스의 메소드 안에서 super 키워드를 사용할 수 있다.
  • static 키워드를 메소드 이름 앞에 붙여주면 해당 메소드는 정적 메소드가 된다.
  • Getter 혹은 Setter를 정의하고 싶을 때는 메소드 이름 앞에 get 또는 set을 붙여주면 된다.
  • extends 키워드를 사용하여 클래스에서 다른 클래스로 상속하면서 클래스의 기능을 확장해 나갈 수 있다.
  • 클래스에서 일반적인 방식으로 property (클래스 내부 변수)를 선언하고 할당하면 public property(공개 변수)이다.
    외부에서 프로퍼티에 접근하여 값을 사용하거나 수정이 가능
  • 클래스에서 property 앞에 # 키워드를 작성하여 선언하면 Private Property (비공개 프로퍼티)가 된다
    오직 클래스 안에서만 사용, 변경이 가능. 외부 접근 불가
class Person{
	constructor(name, age){
		this.name = name;
		this.age = age;
	}
	nextYearAge(){   // 메서드 생성
		return Number(this.age)+1;
	}
}

// 클래스 상속
class introducePerson extends Person{
	constructor(name, agte, city, futureHope){
		// super 키워드를 이용해서 자식 class에서 부모 메서드를 호출
		super(name, age, city);
		this.futureHope = futureHope;
	}
	introduce(){
		return `저는 ${this.city}에 사는 ${this.name} 입니다.
		sosusdps ${super.nextYearAge()} 살이며,
		장래희망은 ${this.futureHope} 입니다.`
	}
}

let kim = new introducePerson('kim', '23', 'seoul', '개발자');
console.log(kim.introduce())

new 키워드를 사용하여 class 메서드와 속성에 액세스 가능

class myClass{
	constructor(name, age){
		this.name = name;
		this.age = age;
	}
}

const user = new myClass('영희', 22);

console.log(user.name);   // 영희
console.log(user.age);    // 22다

다른 class에 상속하려면 extends 키워드 다음에 상속할 class의 이름을 사용

class myClass{
	constructor(name, age){
		this.name = name;
		this.age = age;
	}

	sayHello(){
		console.log(`안녕 ${this.name} 너의 나이는 ${this.age} 살이다.`);
	}
}

class UserProfile extends myClass{
	userName(){
		console.log(this.name);
	}
}

const profile = new UserProfile('영희', 22);

profile.sayHello();   // 안녕 영희 너의 나이는 22살이다.
profile.userName();   // 영희

클래스는 상속과 다형성과 같은 객체 지향 프로그래밍(OOP)의 개념을 구현하기 위한 기반을 제공한다. 자식 클래스를 만들고 부모 클래스의 속성과 메서드를 상속받을 수 있다.

이를 통해 코드의 재사용성과 유지 보수성을 향상시킬 수 있음.

Array and object destructing

객체와 배열의 값을 쉽게 변수로 저장할 수 있음

객체에서 값을 꺼낼 때는 중괄호를 사용해서 key와 같은 이름으로 꺼내올 수 있고, key와 다른 이름으로 꺼낼 때는 변수이름: 키 값으로 꺼내올 수 있다.

객체 분해 할당

  • ES5 문법
const contacts = {
	name: 'unknown',
  age: 23
};

let myName = contacts.name;
let myAge = contacts.age;

console.log(name); // unknown
console.log(age);  // 23
  • ES6 문법

    📌 속성 이름과 동일하지 않은 변수에 할당하면 undefined가 반환됨.
    예를 들어, 속성의 이름이 name이고 username 변수에 할당하면 undefined를 반환

항상 속성의 이름과 동일하게 변수 이름을 지정해야 함. 그러나 변수의 이름을 바꾸려면 콜론을 : 대신 사용하여 가능함

const introduce = {name: 'unknown', age: 23};
// key와 같은 이름으로 변수 선언
const {name, age} = introduce;
// 다른 이름으로 변수 선언 -> 변수이름: 키 값
const {myName: name, myAge: age} = introduce;

console.log(myName);  // unknown
console.log(myAge);   // 23

배열에서 값을 꺼낼 때는 대괄호를 사용해서 앞에서부터 순차적으로 꺼내올 수 있다.

배열 분해 할당

const fruit = ['apple', 'mango', 'grape'];
// 앞에서부터 순차적으로 변수 선언 가능
const [zero, one, two] = fruits;

console.log(zero); // apple

Rest Parameter and Spread Operator

Rest Parameter

Rest Parameter(나머지 매개변수)는 나머지 후속 매개변수들을 묶어 하나의 배열에 저장해서 사용하는 것이다.

묶어줄 매개변수 앞에 을 붙여서 작성하면 된다.

즉, Rest Parameter는 배열과 함수의 인자 중 나머지를 가리키며, 객체의 나머지 필드를 가리킨다.

function func1(...args){
	console.log(`args: [${args}]`)
	// args: [1, 2, 3, 4, 5]
}
func1(1, 2, 3, 4, 5);

function func2(arg1, arg2, ...arg3){
	console.lof(`arg1: ${arg1} , arg2: ${arg2}, arg3: [${arg3}]`)
	// arg1: 1, arg2: 2, arg3: [3, 4, 5]
}
func2(1, 2, 3, 4, 5);

func(인자1, 인자2, …인자들)로 넘겨주게 되면 인자1, 인자2처럼 지정된 인자는 앞에서부터 각각의 값을 넣어주고 그 뒤의 나머지 후속 인자들을 배열에 인자들로 묶어서 보내주는 것이다.

Rest Operator는 함수 정의에는 하나의 만 존재할 수 있으며, 반드시 마지막 매개변수여야 한다.

func(...wrong, arg2, arg3)
// 틀린 예 (...wrong이 마지막으로 와야 한다.)

Spread Operator

Spread Operator(전개 구문)는 묶인 배열 혹은 객체를 개별적인 요소로 분리한다. 즉, Rest와 반대 개념이라고 생각하면 되고, 마찬가지로 전개할 매개변수 앞에 을 붙여서 작성하면 된다.

→ for 반복문이나 다른 메서드를 사용하는 대신 Spread Operator를 사용하여 배열의 값을 가져올 수 있다.

따라서, 배열과 함수에선 또 다른 배열과 함수의 인자로의 전개를, 객체에선 또 다른 객체로의 전개를 한다.

let arr = [1, 2, 3, 4, 5];
console.log(...arr);
// 1 2 3 4 5

var str = 'Hello';
console.log(...str);
// "H" "e" "l" "l" "o"

Spread Operator도 Rest Operator와 마찬가지로 작성 순서에 주의해야 한다. 등장 순서에 따라, 덮어씌워 질 수 있기 때문이다.

var obj = {name: '짱구', species: 'human'};
obj = {...obj, age: 5};

console.log(obj);

obj = {...obj, name: '짱아', age: 1};

console.log(obj);

위 예제와 같이 …obj가 먼저 나오고 name과 age가 나중에 등장함으로써 덮어씌워져 값이 변경된 것을 확인할 수 있다.

요약하자면, Rest Operator(나머지 매개변수)는 배열로 묶는 역할을, Spread Operator(전개 구문)는 개별적인 요소로 분리하는 역할을 한다.

둘 다 을 붙여서 사용하며, 작성 순서에 주의해야 한다.

Spread 연산자와 Rest 매개변수의 차이

Spread 연산자는 배열이나 객체를 분해하거나 복사하는 데 사용되는 반면, Rest 매개변수는 함수 매개변수로 가변 개수의 인자를 배열로 수집하는 데 사용

forEach()/ map()/ reduce()

forEach()map()은 반복문을 돌며 배열 안의 요소들을 1대1로 짝지어 주는 역할을 한다.

forEach(): 배열 요소마다 한 번씩 주어진 함수 (콜백)실행

배열.forEach((요소, 인덱스, 배열) ⇒ {return 요소});

map(): 배열 내의 모든 요소 각각에 대하여 주어진 함수(콜백)를 호출한 결과를 모아 새로운 배열을 반환

배열.map((요소, 인덱스, 배열) ⇒ {return 요소});

하지만 forEach()map()은 역할은 같지만, 리턴값의 차이가 있다.

forEach()는 기존의 배열을 변경하는 반면, map()은 결과값으로 새로운 배열을 반환한다.

var arr = [1, 2, 3, 4, 5];

// forEach()
var newArr = arr.forEach(function(e, i){
	return e;
})
// return -> undefined

// map()
var newArr = arr.map(function(v, i, arr){
	return v + 1;
})
// return -> 2, 3, 4, 5, 6

reduce(): 배열의 각 요소를 순회하며 callback 함수의 실행 값을 누적하여 하나의 결과값을 반환

배열.reduce((누적값, 현재값, 인덱스, 요소) ⇒ {return 결과}, 초깃값);

result = sum.reduce((prev, curr, i) => {
	console.log(prev, curr, i);
	return prev+curr;
}, 0);
// 0 1 0
// 1 2 1
// 3 3 2
result; // 6
  • 초기값을 적어주지 않으면 자동으로 초기값이 0번째 인덱스의 값이 된다.
  • reduce()는 초기값을 배열로 만들고, 배열에 값들을 push하면 map과 같아진다.

Default Parameters

  • 매개 변수가 일부 빠졌을 경우, 선언한 매개변수 순서대로 매핑되고 그 이후는 기본 값으로 들어감
  • 매개 변수를 쓰지 않은 경우 매개 변수가 이미 기본 값에 정의되어 있으므로 정의되지 않은 오류가 반환되지 않는다.
    따라서 누락된 매개 변수를 사용하여 함수를 실행할 때 기본 매개 변수 t 값을 사용하고 오류를 반환하지 않는다.
const myFunc = (name, age) => {
	return `안녕 ${name} 너의 나이는 ${age}살 이니?`;
};

console.log(myFunc1('영희'));
// 출력 => 안녕 영희 너의 나이는 undefined살 이니?

위의 함수는 정의되지 않은 상태로 반환 두 번째 매개 변수 age를 지정하는 것을 잊어버렸기 때문이다.

그러나 기본 매개 변수를 사용하면 정의되지 않은 매개 변수가 반환되지 않고 매개 변수 할당을 잊어버렸을 때 해당 값이 사용된다.

const myFun = (name, age = 22) => {
	return `안녕 ${name} 너의 나이는 ${age}살 이니?`;
};

console.log(myFunc1('영희'));
// 출력 => 안녕 영희 너의 나이는 22살 이니?

Promise

자바스크립트에서 비동기 처리를 기존에는 콜백 함수를 사용한, 콜백 패턴을 사용하였지만 결과적으로 콜백헬이 발생

이를 해결하기 위해 프로미스가 도입되었고, 프로미스 후속처리 메소드를 이용하여 에러 처리를 효과적으로 할 수 있게 되었다.

const myPromise = () => {
	return new Promise((resolve, reject) => {
		resolve('안녕하세요 Promise가 성공적으로 실행했습니다.')
	});
};
console.log(myPromise());
// Promise {<resolve>: "안녕하세요 Promise가 성공적으로 실행했습니다."}

콘솔을 기록하면 Promise가 반환된다. 따라서 데이터를 가져온 후 함수를 실행하려면 Promise를 사용. Promise는 두 개의 매개 변수를 사용하며 resolvereject 예상 오류를 처리할 수 있다.

📌 fetch 함수는 Promise 자체를 반환

const url = 'https://jsonplaceholder.typicode.com/posts';
const getData = (url) => {
	return fetch(url);
};
getData()
  .then((result) => {
    console.log(result); // 성공적인 결과 출력
  })
  .catch((error) => {
    console.error(error); // 에러 메시지 출력
  })
  .finally(() => {
    console.log('Cleanup'); // 항상 실행되는 코드
  });
  • then: 작업이 성공적으로 완료되면 then 메서드를 사용하여 이행 상태에 대한 처리를 할 수 있음
  • catch: 작업이 실패하면 catch 메서드를 사용하여 거부 상태에 대한 처리를 할 수 있음
  • finally: 작업이 완료되었을 때 어떤 처리든 항상 실행할 수 있음

Reference

https://github.com/lukehoban/es6features
https://www.freecodecamp.org/news/write-less-do-more-with-javascript-es6-5fd4a8e50ee2/

profile
Welcome! This is cocoball world!

0개의 댓글