Javascript 문법 훑어보기

mmra-mra·2023년 8월 6일

문법 훑어보기

목록 보기
1/3

Javascript 개발 경험이 없는 사람이 JS로 쓰인 프로젝트를 빠르게 이해하기 위해서 필요했던 내용을 간단하게 정리한 글이다.

마지막 업데이트: 2023-08-12

연산자

Equality(==) vs Strict Equality(===)

Equality는 두 피연산자의 타입이 다를 경우 타입 변환을 시도해 값을 비교한다. Strict Equality는 타입 변환을 하지 않는다.

1 == new Number(1) // true, Number을 원시 객체로 변환
1 === new Number(1) // false

1 == true // true, boolean을 number로 변환
1 === true // false

1 == '1' // true, 문자열을 number로 변환
1 === '1' // false

Optional chaining (?.) vs Nullish coalescing operator (??)

Optional chaining은 참조하려는 객체가 Nullish(undefined이거나 null)이면 error를 던지지 않고 short circuit으로 undefined를 반환한다.

const person = {
 name: string;
}

person?.age; // valid, return undefined
person?.age?.myFunc1()?.myFunc2(); // return undefined from person?.age

Nullish coalescing operator은 좌항이 Nullish이면 우항을 반환하고, 그렇지 않으면 좌항을 반환한다.

const foo = null ?? 'default'; // return 'default'

cf) TypeScript optional property (?)
Typescript의 property가 optional임을 표시하려면 property name에 '?'를 붙인다.

type Person = {
 name: string;
 age?: number;
}

let person: Person = {
	name: "abc";,
} // valid

값을 할당하지 않은 optional field를 참조하면 undefined를 반환한다. 반대로 optional field에 undefined를 assign 할 수 있다.

비동기 처리

Promise

Promise는 비동기 작업의 return value를 나타낸다. 비동기 작업의 성공 여부에 따라서 promise를 매개변수로 하는 함수를 호출할 수 있다.

let testPromise = new Promise((resolve, reject) => {
	const response = sendServerRequest();
    if(response.status === 'SUCCESS') {
    	resolve(response);
    } else {
    	reject(response):
    }
});

testPromise.then((response) => { // 비동기 함수에서 resolve()를 호출할 때 실행
	console.log('SUCCESS');
    console.log(JSON.stringify(response.data));
}, (response) => { // 비동기 함수에서 reject()를 호출할 때 실행
	console.log('FAIL');
});

then()은 또 다른 promise 객체를 반환한다. 따라서 아래와 같이 코드를 작성할 수 있다.

testPromise.then((response) => {
	console.log('SUCCESS');
    return response.data;
}.then((response) => {
	console.log(JSON.stringify(reponse);
})

then()은 항상 Promise를 반환하기 때문에, 일반 객체를 return하는 경우 이를 Promise로 감싸서 반환한다.

참고하면 좋은 글
https://www.daleseo.com/js-async-promise/

Promise Method

여러 개의 Promise를 사용하기 위한 메서드를 제공한다.

// 모든 Promise가 이행된 후 실행
Promise.all([promise1, promise2]).then( ... );

// 한 개의 Promise가 이행되면 바로 실행
Promise.any([promise1, promise2]).then( ... );

// 첫 번째로 이행된 Promise를 인자로 실행
Promise.race([promise1, promise2]).then( ... );

Async, Await

Async 함수는 암시적으로 Promise 객체를 반환한다.

async function foo() {
	return 1
}

// 위의 Async 함수와 동일하게 동작
function foo() {
	return Promise.resolve(1)
}

await 키워드는 Async 함수 내에서 함수의 동작을 잠시 멈추고 다른 비동기 함수가 완료되기를 기다릴 때 사용한다.

function foo1(url) {
  return requestData(url) // returns a promise
    .catch(e => {
      return fail(url) // returns a promise
    })
    .then(v => {
      return success(v); // returns a promise
    });
}

// 위의 promise chain과 동일하게 동작
async function foo2(url) {
  let v;
  try {
    v = await fail(url);
  } catch (e) {
    v = await processError(url);
  }
  return success(v);
}

동작 원리

Javascript는 Single Thread를 사용하지만 Event Queue와 Web API를 이용해 비동기 작업을 수행할 수 있다. Web API를 이용해 setTimeout() 같은 비동기 작업을 수행하고, 완료한 작업은 Event Queue에 넣어놨다가 Call Stack이 비면 Event Queue의 작업을 Call Stack으로 넣어서 이어서 작동한다.

참고하면 좋은 글
https://gruuuuu.github.io/javascript/async-js/

동작 원리를 고려했을 때, Javascript의 비동기 함수는 두 가지 특징을 갖는다.

  1. 비동기 작업이 끝나도 현재 Call Stack에 다른 함수가 있으면 해당 작업이 끝난 후 비동기 함수의 return 값을 처리한다. 예를 들어 setTimeout(5)으로 지정한 시간이 끝나도 call stack에 다른 값이 있으면 5ms보다 더 늦게 callback 함수를 호출한다.
const start = Date.now();

setTimeout(()=>console.log(`timeout ${(Date.now() - start)}`), 5);
// result: timeout 6
const start = Date.now();

setTimeout(()=>console.log(`timeout ${(Date.now() - start)}`), 5);
let i = 0;
while(i < 999999999) { i++; }
// result: timeout 593
  1. 두 개의 다른 비동기 함수에서 호출하는 callback 함수는 순차적으로 동작한다. 즉, 아래 코드의 결과값은 1234 혹은 3412이다. 1324 같은 결과는 나오지 않는다.
setTimeout(()=>{
    console.log(1);
    let i = 0;
    while(i < 999999999) { i++; }
    console.log(2);
}, 5);
    
setTimeout(()=>{
    console.log(3);
    console.log(4);
}, 5);

2개의 댓글

comment-user-thumbnail
2023년 8월 6일

잘 읽었습니다. 좋은 정보 감사드립니다.

1개의 답글