JavaScript 기초 지식 정리 (2)

SERI·2022년 5월 15일
0

📂 배열

1. 배열 만들기

const arr1 = new Array();
const arr2 = [1, 2]; // 더 많이 쓰는 방법

2. index

const fruits = ['사과', '바나나'];
console.log(fruits); // ['사과', '바나나']
console.log(fruits[0]); // 사과

3. 배열 출력 방법

  • for
  • for of
for(let fruit of fruits) {
    console.log(fruit);
}
  • forEach
fruits.forEach((fruit) => console.log(fruit));

4. 배열 addition, deletion, combine

  • addition
 fruits.push('포도', '복숭아');
  • deletion
fruits.pop();
  
 <지정된 곳의 아이템 지우기>
fruits.splice(2);  
// 1 부터 다 지워짐
fruits.splice(1, 1, '수박'); 
// 인덱스 1부터 한 개를 지우고 수박을 넣어라
  • unshift, shift도 있으나 push, pop 사용

  • combine

const fruits2 = ['청사과', '포도'];
const newFruits = fruits.concat(fruits2);

5. searching

  • indexOf
console.log(fruits.indexOf('수박')); // 수박의 인덱스?
  • includes
console.log(fruits.includes(사과)); // 사과가 배열에 있는가?
  • lastIndexOf
console.log(fruits.indexOf('사과'));
// 앞에서부터 가장 먼저 있는 사과가 몇 번째?
console.log(fruits.lastIndexOf('복숭아'));
// 가장 뒤에 있는 복숭아가 몇 번째에 위치?


📄 JSON (JavaScript Object Notion)

  • 클라이언트와 서버 간 데이터 교환을 위한 규칙 (데이터포맷)

  • 특징

    • simplest data interchange format
    • light weight text-based structure
    • easy to read
    • key-value paris
    • used for serialization and transmission of data between the network connection
    • independent programming language and platform

1. object to Json (serialize)

  • stringify - 객체를 JSON 형식의 문자열로 변환

  • 불리언을 json으로

let json = JSON.stringify(true);
console.log(json); -> true
  • 배열을 json으로
json = JSON.stringify(['apple', 'banana']);
console.log(json);  // ["apple","banana"]
  • object를 json으로
    const rabbit = {
          name: 'tori',
          color: 'white',
          size: null,
          birthDate: new Date(),
          jump: () => {
              console.log(`${this.name} can jump!`); 
          }, // jump는 json에 포함 되지 않음
          함수는 오브젝트에 있는 데이터가 아니라서.
          자바 스크립트에 있는 특별한 데이터도 포함되지 않음 (symbol)
      };
      json = JSON.stringify(rabbit);
      console.log(json); 
      // {"name":"tori","color":"white",
      "size":null,"birthDate":"2022-05-13T06:29:53.033Z"}

2. JSON to object (deserialize)

  • parse : JSON 데이터를 가진 문자열을 객체로 변환
json = JSON.stringify(rabbit);
const obj = JSON.parse(json,(key, value) => {
    console.log(`key: ${key}, value: ${value}`);
    return key === 'birthDate' ? new Date(value) : value;
});
console.log(obj);

console.log(rabbit.birthDate.getDate()); //13
console.log(obj.birthDate.getDate());
// error! object를 json으로 만들었을 때 string형태였음. 
이걸 다시 object로 바꿀 때도 string이 됨.
// 이럴 경우 다시 세밀하게 date로 변환하고 싶으면
callback 함수 이용하면 결과 정상적으로 나옴

3. JSON 유용한 사이트

  • jsondiff.com
    서버에게 요청했을 때 첫 번째로 받아온 데이터와 두 번째로 받아온 데이터가 어떻게 다른지 모를 때 비교 가능
  • json beautifiler
    서버에서 받아온 json을 붙여넣기하면 포맷이 망가질 때 있는데 정리 가능
  • json parser
    제이슨 타입을 오브젝트 형태로 확인해보고 싶을 때
  • json validator
    유효한 json data인지 확인할 수 있음

🕐 동기적 / 비동기적

  • JavaScript is synchronous (동기적-순차적)
  • Execute the code block in order after hoisting


1. 비동기적(병렬적) 실행방법

console.log('1'); // 동기
setTimeout(() => console.log('2') , 1000); // (콜백함수, 시간)
비동기 / 브라우저 API이기 때문에 
브라우저에게 1초 뒤에 실행하라고 요청함
console.log('3'); // 1 3 2

2. 동기 callback

function printImmediately(print) {
    print();
}
printImmediately(() => console.log('hello')); // 동기

3. 비동기적 callback

function printWithDelay(print, timeout) {
    setTimeout(print, timeout);
}

printWithDelay(() => console.log('async callback'), 2000); 
// 비동기


👻 callback hell

  • 가독성 떨어짐
  • 비즈니스 로직 알기 어려움
  • 디버깅 어려움
  • 유지 보수 어려움
class UserStorage {
    loginUser(id, password, onSuccess, onError) {
        setTimeout(() => {
            if (
                (id === 'seri' && password === 'seri') ||
                (id === 'coder' && password === 'academy')
            ) {
                onSuccess(id);
            } else{
                onError(new Error('not found'));
            }
        }, 2000);
    } 
    
    getRoles(user, onSuccess, onError){
        setTimeout(() => {
            if (user === 'seri') {
                onSuccess({ name: 'seri', role: 'admin'});
            } else {
                onError(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,
    user => {
        userStorage.getRoles(
            user,
            userWithRole => {
                alert(`Hello ${userWithRole.name}, you have a ${userWithRole.role} role`);
            }, 
    error => {
        console.log(error);
    }
    ); 
},
error => {
    console.log(error);
}
);

  • 콜백 -> 프로미스

class UserStorage {
    loginUser(id, password) {
        return new Promise((resolve, reject) => { 
        // 콜백함수 필요 없다. success, error
        setTimeout(() => {
            if (
                (id === 'seri' && password === 'seri') ||
                (id === 'coder' && password === 'academy')
            ) {
                resolve(id);
            } else{
                reject(new Error('not found'));
            }
        }, 2000);
    });
}
    getRoles(user) { 
       return new Promise((resolve, reject) => {
           setTimeout(() => {
               if (user === 'seri') {
                   resolve({ name: 'seri', 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(userStorage.getRoles)
.then(user => alert(`Hello ${user.name}, you have a ${user.role} role`))
.catch(console.log);

🤙 promise

  • 콜백을 쓰지 않고 비동기를 간편하게 처리할 수 있도록 도와주는 오브젝트
  • promise is a JavaScript object for asynchronous operation.
  • 함수를 매개변수로 받음
  • 포인트
    • state
    • producer와 consumer 차이점
  • state
    • pending(수행 중) / result: undefined
    • fulfilled / result: value // resolve(value)
    • rejected / result: error // regect(error)

1. producer

네트워크에서 데이터를 받아오거나 파일에서 큰 데이터를 읽어오는 것은 시간이 오래 걸림 (heavy work) 이를 동기적으로 처리하게 되면 처리하는 동안 그 다음 라인 코드가 실행되지 않기 때문에 시간이 걸리는 것은 프로미스를 만들어 비동기적으로 처리하는 것이 좋음

  • when new promise is created, the executor runs automatically
  • promise는 calss
  • promise를 만드는 순간 콜백함수 바로 실행
    • 네트워크 요청을 사용자가 요구했을 때만 해야하는 경우라면 유의해야함
  • resolve
    • 성공. resolve()에 값을 저장하게 됨
  • reject
    • 실패. Error는 자바스크립트에서 제공하는 object다. 에러가 발생했다는 오브젝트임. 에러의 이유를 같이 써준다 (no network).


2. consumers

  • then
    • chaining
      • promise의 then을 호출하게 되면 then은 결국 똑같은 promise를 return하기 때문에 리턴된 프로미스에 catch를 다시 호출할 수 있다
    • then은 promise가 정상적으로 수행된 후 마지막에 resolve라는 콜백함수를 통해 전달한 값이 value의 파라미터로 전달
    • 값의 첫 번째 함수는 성공 시, 두 번째 함수는 실패 시
  • catch
    • 에러 발생 시 처리 방법 (state: rejected일 때 실행)
  • finally
    • 성공(fulfuilled), 실패(rejected)와 관계없이 마지막에 실행

const promise = new Promise((resolve, reject) => {
    // doing some heavy work
    console.log('doing something'); 
    setTimeout(() => {
        resolve('seri'); 
        reject(new Error('no network')) 
    }, 2000);

<chaining>

promise
.then((value) => {
// resolve의 값을 받아 옴.
then은 값을 전달해도 되고,프로미스를 전달해도 된다.
  console.log(value)
}) 
.catch(error => {
    console.log(error);
})
.finally(() => {
    console.log('finally');
});


<promise chaining>
const fetchNumber = new Promise((resolve, reject) =>{
    setTimeout(() => resolve(1), 1000);
});

fetchNumber
.then(num => num * 2)
.then(num => num * 3)
.then(num => {
    return new Promise ((resolve, reject) => {
        setTimeout(() => resolve(num - 1), 1000);
        });
})

.then(num => console.log(num));

  • error handling
    const getHen = () =>
    new Promise((resolve, reject) => {
        setTimeout(() => resolve('🐔'), 1000);
    });
    const getEgg = hen =>
    new Promise((resolve, reject) => {
        setTimeout(() => resolve(`${hen} => 🥚`), 1000);
    });
    const cook = egg =>
    new Promise((resolve, reject) => {
        setTimeout(() => resolve(`${egg} => 🍳`), 1000);
    });    

    getHen()
    .then(hen => getEgg(hen))
    .then(egg => cook(egg))
    .then(meal => console.log(meal));

 // 받아온 value를 다른 함수로 바로 호출하는 경우에 생략 가능
 // 자동적으로 then에서 받아오는 value를 바로 getEgg라는 함수로 전달
 // getHen()을 축약해서 작성한 것
	getHen()
	.then(getEgg)
	.then(cook)
	.then(console.log);
 // 달걀을 받아오면서 에러가 생겼을 때 다른 재료로 대체하는 방법
 getHen()
    .then(getEgg)
    .catch(error => {
        return '🥖';
    })
    .then(cook)
    .then(console.log);
  • Promise.all
    • 모든 프로미스가 실행되는 시간을 단축시켜줌

🪄 async & await

  • clear style of using promise
  • 상황에 따라 프로미스와 async & await를 씀
  • async는 항상 프로미스를 반환

1. 동기적으로 실행 했을 때

  • 비동기적으로 처리하지 않으면 사용자 데이터를 받아 올 때 10초가 걸려서 만약 뒤 웹페이지의 ui를 표시하는 기능을 수행하는 코드가 있다면, 이 함수가 처리되는 동안 데이터가 웹페이지에 표시되지 않기 때문에 사용자는 10초 정도 빈 페이지만 보게 됨. 이렇게 오래걸리는 일은 비동기적으로 처리.
function fetchUser() {
         // do network request in 10 secs...
         // 함수 실행 시간 10초
        return 'seri';
    }

const user = fetchUser();
console.log(user);

2. promise로 했을 때

function fetchUser() {
    return new Promise((resolve, reject) => {
         // do network request in 10 secs...
         resolve('ellie');
    })
}

const user = fetchUser();
user.then(console.log)
console.log(user); 

3. async

  • promise를 쓰지 않아도 자동적으로 코드 블럭들이 프로미스로 변환됨
async function fetchUser() { 
         // do network request in 10 secs...
         return 'ellie';
    }

const user = fetchUser();
user.then(console.log)
console.log(user); 

4. await

  • async가 붙은 함수 안에서만 쓸 수 있다
  • 뒤에 프로미스를 적고 await는 프로미스가 처리될 때까지 기다림
function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function getApple() {
    await delay(3000);
    throw 'error'; // 에러 발생하게 하는 코드
    return '사과';
}

async function getBanana() {
    await delay(3000);
    return '바나나';
}

// 바로 위 함수와 같은 기능 (안 좋은 예)
function getBanana() {
    return delay(3000)
    .then(() => '바나나');
}
  • 과일을 한번에 다 따는 함수. 콜백 지옥과 비슷한 모습.
function pickFruits() {
    return getApple()
    .then(apple => {
        return getBanana()
        .then(banana => `${apple} + ${banana}`);
    });
}

pickFruits().then(console.log);
  • async로 간단하게 하자
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);
profile
절망의 계곡을 탈출하자

0개의 댓글