정리 기준
1. 평소에 사용하면서도 애매하게 알고 있었던 것
2. 있다는 건 알고 있지만 사용하려고 하면 맨날 오류나서 결국 사용하지 못하는 개념들
<head>
<script src="main.js"></script>
</head>
<body>
...
<script src="main.js" async></script>
</body>
<head>
<script src="main.js" async></script>
</head>
<head>
<script src="main.js" defer></script>
</head>
Getter and Setter
class User {
constructor(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
get age() {
// 위에 있는 this.age;는 메모리를 읽어오는 것이 아니라
// 이 getter를 호출하게 됨
return this._age;
}
// setter를 정의하는 순간 위에서 = age;를 호출할 때(값을 할당할 때),
// 메모리에 값을 할당하는 게 아니라 이 setter를 호출하게 됨
// 이 말은, setter 안에서 전달된 value를 age에 할당 할 때,
// 메모리에 값을 할당하는게 아니라 setter를 호출하게 됨. 그러면 무한 반복
// 따라서 getter와 setter에 쓰여지는 변수는 이름을 다르게 쓴다
set age(value) {
//
this._age = value;
}
}
Public field and Private field
class Experiment {
publicField = 2;
#privateField = 0;
}
const experiment = new Experiment();
console.log(experiment.publicField); // 2
console.log(experiment.privateField); // undefined
Static properties and methods
class Article {
// object에 상관 없이 class 자체에 연결되어 있음
static publisher = 'Dream Coding';
constructor(articleNumber) {
this.articleNumber = articleNumber;
}
static printPublisher() {
console.log(Article.publisher);
}
}
const article1 = new Article(1);
console.log(article1.publisher); // undefined
console.log(Article.publisher); // Dream Coding
Article.printPublisher(); // Dream Coding
for ... in vs. for ... of
// for (key in obj)
for (key in ellie) {
console.log(key); // ellie 안에 있는 모든 키 출력
}
// for (value of iterable)
const array = [1, 2, 3];
for (value of array) {
console.log(value);
}
Cloning
const user = { name: 'ellie', age: 20 }
const user2 = user;
// user는 레퍼런스가 들어있는 메모리를 가리키고 있고, 그 레퍼런스는 데이터를 가지고 있는 오브젝트를 가리킨다
// user2의 변수는 user안에 있는 레퍼런트의 값이 동일한 레퍼런스가 들어있음, 따라서 똑같은 오브젝트를 가르킴
user2.name = 'coder';
console.log(user); // { name: 'coder', age: 20 }
// 위가 아니라 진짜 복사를 하고 싶다면
// old way
const user3 = {};
for (key in user) {
user3[key] = user[key];
}
// new way
const user4 = {};
Object.assign(user4, user); // Object.assign(target, source);
// 위 두줄을 한줄로 하면
const user4 = Object.assign({}, user);
// 여러 오브젝트를 줄 수 있음
const mixed = Object.assign({}, fruit1, fruit2);
// 동일한 키가 있다면 뒤에 있는 값이 계속 덮어 씌움
Object to JSON
// stringify converts a JavaScript value to a JavaScript Object Notation(JSON) string.
let json = JSON.stringify(true);
console.log(json); // true
json = JSON.stringify(['apple', 'banana']);
console.log(json); // ["apple", "banana"] -> "" 사용은 JSON의 규격 사항
const rabbit = {
name: 'tori',
color: 'white',
size: null,
birthDate: new Date(),
jump: () => {
console.log(`${this.name} can jump!`);
}
};
json = JSON.stringify(rabbit);
console.log(json);
// {"name":"tori", "color":"white", "size":null,"birthDate":"2022-01-10어쩌구"}
// jump 함수는 제외됨, 데이터가 아니기 때문
// symbol같이 JS에만 있는 특별한 데이터도 포함되지 않음
json = JSON.stringify(rabbit, ["name", "color"]);
console.log(json); // {"name":"tori", "color":"white"}
json = JSON.stringify(rabbit, (key, value) => {
console.log(`key: ${key}, value: ${value}`);
return value;
// 결과는 아래 이미지
});
json = JSON.stringify(rabbit, (key, value) => {
console.log(`key: ${key}, value: ${value}`);
return key === 'name' ? 'ellie': value;
});
console.log(json); // {"name":"ellie", "color":"white", "size":null,"birthDate":"2022-01-10어쩌구"}
JSON to Object
// parse converts a JavaScript Object Notation(JSON) string into an object.
json = JSON.stringify(rabbit);
const obj = JSON.parse(json);
console.log(obj);
// {name: "tori", color: "white", size: null, birthDate: "2022-01-10어쩌구"}
// stringify를 할 때 함수는 변환되지 않기 때문에 parse한 결과에서도 함수가 없다
rabbit.jump(); // tori can jump!
obj.jump(); // jump is not a function
console.log(rabbit.birthDate.getData()); // 10
// 값이 그냥 string이기 때문.. rabbit에 있던 birthDate은 데이트라는 오브젝트 였었다
console.log(obj.birthDate.getData()); // getDate is not a function
// 세밀하게 parse 하고 싶을 때
const obj = JSON.parse(json, (key, value) => {
return key === 'birthDate' ? new Date(value) : value;
}
console.log(obj.birthDate.getDate); // 10
class UserStorage {
loginUser(id, password) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (
(id === 'ellie' && password === 'dream') ||
(id === 'coder' && password === 'academy')
) {
resolve(id);
} else {
reject(new Error('not found');
}
}, 2000);
}
});
// 사용자의 데이터를 받아서 그 정보를 바탕으로 백엔드에 해당 사용자의 역할을 요청해서 받아오는 api
getRoles(user) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (user === 'ellie') {
resolve({ name: 'ellie', role: 'admin' });
} else {
reject(new Error('no access');
};
}, 1000);
});
}
}
const userStorage = new UserStorage();
const id = prompt('enter your id');
const password = prompt('enter your password');
userStorage
// 로그인을 하고
.loginUser(id, password)
// 로그인에 성공하면 그 유저를 이용해서 역할을 받아오고
.then(user => userStorage.getRoles)
// 그것에 성공하면 alert를 띄운다
.then(user => alert(
`Hello ${user.name}, you have a ${user.role} role`
))
.catch(console.log);
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function getApple() {
// await을 쓰면 delay가 진행되는 3초동안 기다려줌
await delay(3000);
// throw 'error';
return '🍎';
}
async function getBanana() {
await delay(3000);
return '🍌';
}
// getBanana를 promise로 써보면 아래와 같이 쓸 수 있다
// 하지만 위와 같이 동기적인 코드를 쓰는 것처럼 하면 쉽게 이해할 수 있음
function getBanana() {
return delay(3000);
.then(() => '🍌');
}
// 아래와 같이 하면 콜백 지옥 비슷해짐
function pickFruits() {
return getApple()
.then(apple => {
return getBanana()
.then(banana => `${apple} + ${banana}`)
})
}
// 위 코드를 async를 써서 해보자
async function pickFruits() {
// try, catch로 에러처리 해줄 수도 있음
const apple = await getApple();
const banana = await getBanana();
return `${apple} + ${banana}`;
}
// 여기서 문제는 사과를 받는데 3초가 지나고 또 바나나를 받는데 3초가 지남
// apple과 banana 사이에는 서로 연관이 없기 때문에 서로를 기다릴 필요가 없다
// 따라서 아래와 같이 해볼 수 었음
// const를 만드는 순간 코드는 실행이 된다, 따라서 미리 만들어두고 await을 건다
// 병렬적으로 실행 가능, 하지만 코드가 정말 더러워짐
// 아래 promise api를 이용해봐
async function pickFruits() {
const applePromise = getApple();
const bananaPromise = getBanana();
const apple = await applePromise();
const banana = await bananaPromise();
return `${apple} + ${banana}`;
}
pickFruits().then(console.log);
// Useful Promise APIs
function pickAllFruits() {
// 프로미스 배열을 전달해주면 모든 프로미스들이 병렬적으로 받을 때까지 모아주는 아이
return Promise.all([getApple(), getBanana()])
// 이 경우 결과가 배열로 받아짐
.then(fruits => fruits.join(' + ');
}
pickAllFruits().then(console.log); // 🍎 + 🍌
// 어떤 과일이던 먼저 따지는 과일 받아오기
function pickOnlyOne() {
// 배열에 전달 된 프로미스 중에서 값을 가장 먼저 리턴하는 아이만 전달되어짐
return Promise.race([getApple(), getBanana()]);
}
pickOnlyOne().then(console.log);
leftExpr ?? rightExpr
- 왼쪽 코드가 null, undefined인 경우에만 오른쪽 코드가 실행된다
leftExpr || rightExpr
- 왼쪽 코드가 falsy인 경우에만 오른쪽 코드가 실행된다
// Bad
function printMessage(text) {
let message = text;
if (text == null || text == undefined) {
message = 'Nothing to display';
}
console.log(message);
}
// Good
function printMessage(text) {
// text가 있다면 그대로 쓰고 없으면 'Nothing to display'
const message = text ?? 'Nothing to display';
console.log(message);
}
printMessage('Hello'); // Hello
printMessage(undefined); // Nothing to display
printMessage(null); // Nothing to display
// 위 함수를 default 값을 준다면?
// undefined인 경우에만 default값이 할당 됨
function printMessage(text = 'Nothing to display') {
console.log(text);
}
printMessage('Hello'); // Hello
printMessage(undefined); // Nothing to display
printMessage(null); // Null
const bob = {
name: 'Julia',
age: 20
};
const anna = {
name: 'Julia',
age: 20,
job: {
title: 'Software Engineer',
}
};
// Bad
function displayJobTitle(person) {
if (person.job && person.job.title) {
console.log(person.job.title);
}
}
// Good
function displayJobTitle(person) {
// job이 있다면 그 job 안에 title이 있는지 아닌지 확인
if (person.job?.title) {
console.log(person.job.title);
}
}
function displayJobTitle(person) {
const title = person.job?.title ?? 'No Job Yet';
console.log(title);
}
fetch('https://codingapple1.github.io/price.json')
.then((response) => {
if (!response.ok) {
throw new Error('Error 400 or Error 500')
}
return response.json()
})
.then((result) => {
console.log(result);
})
.catch(() => {
console.log('에러남');
})
OR
async function fetchingData() {
let response = await fetch('https://codingapple1.github.io/price.json');
if (!response.ok) {
throw new Error('Error 400 or Error 500');
}
let result = await response.json();
console.log(result);
}
fetchingData().catch(() => {
console.log('에러남');
})
Youtube 자바스크립트 기초 강의 by 드림코딩