수업을 듣고 내용을 정리한 글입니다.
ES6부터는 변수를 선언할 때 let
또는 const
를 사용할 수 있다.
let
과 const
, 그리고 var
는 어떤 차이점이 있을까?
var
는 전역 범위 또는 함수 범위이며, let
과 const
는 블록 범위이다.
여기서 블록은 중괄호 속에 있는 모든 코드이다.
하나의 블록은 중괄호 속에 존재하며, 중괄호 안에 있는 모든 것은 블록 범위이다.
// var
if (false) {
var example1 = 5;
}
console.log(example1); // undefined
// let, const
if (true) {
let example2 = 5;
const example3 = 10;
console.log(example2); // 5
console.log(example3); // 10
}
console.log(example2); // ReferenceError: example2 is not defined
console.log(example3); // ReferenceError: example3 is not defined
위 코드에서 var
로 선언한 example1은 전역 범위여서 if문 외부에서도 사용할 수 있다. 또한 오류가 아닌 undefined가 뜬 모습.
그에 비해 let
으로 선언한 example2, const
로 선언한 example3은 블록 범위이기 때문에 if문 외부에서 사용이 불가능하다.
var
와 let
은 초기화하지 않은 상태로 선언할 수 있지만, const
는 선언 중에 초기화해야한다.
// var
var first;
first = 10; // 오류 없음
// let
let second;
second = 20; // 오류 없음
// const
const c; // SyntaxError: Missing initializer in const declaration
var
는 범위 내에서 재할당 및 재선언할 수 있다.
let
은 재할당할 수 있지만, 재선언은 할 수 없다.
const
는 재할당과 재선언 둘 다 불가능하다.
// var
var hello = "Say hi"
var hello = "Say hello" // 재선언 가능
hello = "Say good morning" // 재할당 가능
// let
let hello = "Say hi";
let hello = "Say good morning"; // SyntaxError: Identifier 'hello' has already been declared
hello = "Say hello"; // 재할당 가능
// const
const hello = "Say hi";
const hello = "Say hello"; // SyntaxError: Identifier 'hello' has already been declared
hello = "Say good morning"; // TypeError: Assignment to constant variable.
호이스팅 : 변수와 함수 선언이 맨 위로 이동되는 매커니즘.
console.log (hi);
var hi = "Say hi"
만약 위와 같이 코드를 짜면, 다음과 같이 해석된다.
var hi;
console.log(hi); // undefined
hi = "Say hi"
그러나 var
대신 let
, const
로 변수를 선언한다면 오류가 발생해 이런 문제를 막아준다. let
과 const
또한 호이스팅이 되지만 var
와는 다르게 undefined로 초기화되지 않기 때문이다.
console.log(hi); // ReferenceError: Cannot access 'hi' before initialization
let hi = "Say hi";
const
로 선언한 배열은 push
, pop
이 가능하다.
const cities = ["Daegu", "Jeonju"];
cities.push("Seoul"); // 오류 없음
console.log(cities); // ['Daegu', 'Jeonju', 'Seoul']
cities.pop("Daegu"); // 오류 없음
console.log(cities); // ['Jeonju', 'Seoul']
const
선언은 재할당이 불가능하다고 했는데, 왜 그런걸까?
push
와pop
은 재할당이나 재선언이 아니기 때문이다(...)
그렇다면 push
와 pop
은 왜 재할당이나 재선언이 아닐까?
const cities = ["Daegu", "Jeonju"];
로 배열cities
의 포인터를 지정한 것이고,
cities.push("Seoul");
,cities.pop("Daegu");
로cities
의 메모리에 접근을 한 것이다.
즉,push
와pop
은 포인터를 건드리지 않았기 때문에 재할당이나 재선언이 아니다.
Destructuring은 배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 기능이다.
// 배열 Destructuring
const number = [1, 2, 3];
// ES5
var num1 = number[0];
var num2 = number[1];
var num3 = number[2];
console.log(num1, num2, num3); // 1 2 3
// ES6
const [num1, num2, num3] = number;
console.log(num1, num2, num3); // 1 2 3
// 객체 Destructuring
const player = {
name: "Gwon",
address: {
city: "Busan"
}
};
// ES5
console.log(player.name, player.address.city); // Gwon Busan
// ES6
const { name, address: { city } } = player;
console.log(name, city); // Gwon Busan
한번에 할 수도 있다.
let [fisrtName, middleName, lastName] = ["Dylan", "Coding God", "Israel"];
console.log(lastName); // Israel
문자열을 `
(백틱) 으로 감싸 사용할 수 있다. 또한, 문자열 안에 변수를 넣을 수도 있다.
${}
안에 변수를 넣으면 된다.
const name = "김철수"
const age = 19
// ES5
console.log("이름 : " + name + ", 나이 : " + age) // 이름 : 김철수, 나이 : 19
// ES6
console.log(`이름 : ${name}, 나이 : ${age}`); // 이름 : 김철수, 나이 : 19
for of
문은 객체를 반복하고, 각각의 속성값을 변수에 할당한다.
let incomes = [6200, 6700, 7500];
let total = 0;
for (const income of incomes) {
console.log(income); // 6200, 6700, 7500
total += income;
}
console.log(total) // 20400
for in
문과는 어떤 차이가 있을까?
let incomes = [6200, 6700, 7500];
for (const income in incomes) {
console.log(incomes[income], income); // 6200 '0' 6700 '1' 7500 '2'
}
for in
에서는 각각의 속성의 인덱스를 반환한 모습이다.
화살표 함수는 화살표 (=>)
를 사용하여 보다 간략한 방법으로 함수를 선언할 수 있다.
// 기존 함수
function add(num1, num2) {
return num1 + num2;
}
var add = function(num1, num2) {
return num1 + num2;
};
// 화살표 함수
const add = (num1, num2) => {
return num1 + num2;
}
만약 함수의 매개변수가 한개라면, 괄호를 생략할 수 있다.
또한, 함수 본문에 하나의 명령문만 있다면 중괄호 또한 생략을 할 수 있다.
const meal = food => `I love ${food}`
console.log(meal("chicken")); // I love chicken
Spread Operator는 반복 가능한 객체를 요소 하나 하나로 전개를 시킬 수 있다.
// 예시
let contacts = ["Mary", "Joel", "Danny"];
let personalFriends = ["David", ...contacts, "Lily"];
console.log(personalFriends); // ['David', 'Mary', 'Joel', 'Danny', 'Lily']
let person = {
name: "Adam",
age: "25",
city: "Manchester"
};
let employee = {
...person,
salary: 50000,
position: "Software Developer"
};
console.log(employee)
// {name: 'Adam', age: '25', city: 'Manchester', salary: 50000, position: 'Software Developer'}
includes()
메서드는 배열이 특정 요소를 포함하고 있는지 판별한다.
let numArray = [1, 2, 3, 4, 5];
console.log(numArray.includes(2)); // true
console.log(numArray.includes(7)); // false
탐색을 몇 번째 index 부터 시작할것인지 지정할 수도 있다.
let numArray = [1, 2, 3, 4, 5];
console.log(numArray.includes(2)); // true
console.log(numArray.includes(2, 3)); // 3번 인덱스부터 탐색하기 때문에 false
class
는 자바스크립트에서 객체 지향 프로그래밍을 지원하기 위해 도입된 문법이다. class
사용하면, 기존에 프로토타입 기반으로 구현되던 객체 생성 방식을 더 직관적으로 사용할 수 있다.
class Animal {
constructor(type, legs) {
this.type = type;
this.legs = legs;
}
makeNoise(sound = "Loud Noise") {
console.log(sound);
}
static makeNoise2(sound) {
console.log(sound);
}
get metaData() {
return `Type : ${this.type}, legs: ${this.legs}`;
}
}
이제 이 클래스를 사용하여 다음과 같이 Animal
인스턴스를 생성할 수 있다.
const cat = new Animal("Cat", 4);
cat.makeNoise(); // Loud Noise
또한 static
메서드는 인스턴스를 생성하지 않고도 사용할 수 있다.
Animal.makeNoise2("meow"); // meow
그리고 get
키워드는 메서드를 객체의 프로퍼티처럼 접근할 수 있도록 할 수 있다.
const cat = new Animal("Cat", 4);
console.log(cat.metaData); // Type : Cat, legs: 4
여기서 metaData
는 메서드가 아닌 getter 이기 때문에 호출할 필요가 없다. 그러니 metaData
뒤에 괄호를 붙이면 안된다.
extends
는 클래스에서 상속을 통해 기존 클래스를 확장할 수 있다.
위에 있는 Animal
클래스를 다음과 같이 상속시킬 수 있다.
class Cat extends Animal {
constructor(type, legs, color) {
super(type, legs)
this.color = color;
}
makeNoise(sound = "meow") {
console.log(sound);
}
get metaData2() {
return `Type : ${this.type}, legs: ${this.legs}, color: ${this.color}`;
}
}
const cat2 = new Cat("Cat", 4, "white");
cat2.makeNoise(); // meow
console.log(cat2.metaData); // Type : Cat, legs: 4
console.log(cat2.metaData2); // Type : Cat, legs: 4, color: white
Animal
클래스에 있던 metaData
를 여전히 쓸 수 있는 모습.
또한 부모 클래스와 생성자가 같다면 constuctor
부분은 생략이 가능하다.
class Cat extends Animal {
makeNoise(sound = "meow") {
console.log(sound);
}
}
export
는 파일 안에 있는 함수나 객체를 내보낼 수 있다.
export const name = "..."
export { v1, v2, v3 ... }
export const func = () => {...}
export class Class {...}
import
는 다른 모듈에서 내보낸 함수나 객체를 가져올 수 있다.
import data from "./example";
import { member1 } from "./team";
import { member2 as name } from "./team";
fetch()
는 웹 브라우저에서 제공하는 네트워크 통신을 위한 API 이다. fetch()
를 사용하면 서버로 HTTP 요청을 보내고, 서버로부터 응답을 받을 수 있다.
fetch(url)
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
위의 코드에서 fetch()
함수는 서버로부터 JSON 형식의 데이터를 요청한다. fetch()
함수가 Promise
를 반환하므로, 이 Promise
를 체이닝하여 데이터를 처리하는 로직을 작성한다.
첫 번째 then()
메서드에서는 Response
객체에서 json()
메서드를 호출하여 JSON 데이터를 추출한다. 이렇게 추출한 데이터는 두 번째 then()
메서드에서 처리하게 된다. 마지막으로 catch()
메서드를 사용하여 예외 처리를 한다.
Promise
는 비동기 작업의 결과를 나타내는 자바스크립트 객체이다. 비동기 작업이란 일반적으로 네트워크 요청이나 파일 로딩 등이 포함된다. Promise
는 이러한 비동기 작업을 좀 더 편리하게 다룰 수 있도록 도와준다.
const promise = new Promise((resolve, reject) => {
// 비동기 작업 수행
if (/* 작업이 성공하면 */) {
resolve(result); // 결과를 resolve()에 전달
} else {
reject(error); // 에러를 reject()에 전달
}
});
promise
.then(result => {
// 비동기 작업이 성공한 경우 실행되는 함수
})
.catch(error => {
// 비동기 작업이 실패한 경우 실행되는 함수
});
Promise 생성자 함수를 호출할 때는, 콜백 함수를 전달한다. 이 콜백 함수는 resolve와 reject라는 두 개의 함수를 인자로 받습니다. 비동기 작업이 성공하면 resolve() 함수에 결과를 전달하고, 실패하면 reject() 함수에 에러를 전달한다.
then() 메서드는 Promise가 resolve되면 실행되는 함수를 등록한다. catch() 메서드는 Promise가 reject되면 실행되는 함수를 등록한다.
async / await
은 ES2017(ES8)에서 도입된 문법으로, Promise
를 기반으로 하고 있다. async
함수는 반드시 Promise
객체를 반환하며, await
키워드를 이용하여 Promise
객체의 처리가 완료될 때까지 코드의 실행을 일시적으로 정지시킬 수 있다.
async function someFunction() {
try {
const result1 = await somePromise1();
const result2 = await somePromise2(result1);
return result2;
} catch (error) {
console.error(error);
}
}
위의 코드에서 async
함수 someFunction
내부에서는 await
키워드를 사용하여 somePromise1()
함수와 somePromise2(result1)
함수를 차례로 호출하고, 각각의 Promise
처리가 완료될 때까지 실행을 일시적으로 중지한다. 이후에는 Promise
객체의 처리가 완료되면 반환된 값을 변수에 저장하고, 마지막에는 최종 결과 값을 반환한다. try-catch
구문을 사용하여 Promise
객체의 처리 중 발생한 에러를 처리할 수도 있다.