클래스를 활용한 상속


class Animal {
  constructor(age, weight) {
    this.age = age;
    this.weight = weight;
  }
  eat() {
    return "eat";
  }
  move() {
    return "move";
  }
}

class Bird extends Animal {
  constructor(age, weight) {
    super(age, weight);
  }

  fly() {
    return "fly";
  }
}




프로토타입을 기반으로 한 상속


const Animal = (function () {
  function Animal(age, weight) {
    this.age = age;
    this.weight = weight;
  }

  return Animal;
})();

const Bird = (function () {
  function Bird(age, weight) {
    Animal.apply(this, [age, weight]);
  }

  Bird.prototype = Object.create(Animal.prototype);
  Bird.prototype.constructor = Bird;

  return Bird;
})();




클래스와 생성자 함수의 차이점


  • 클래스는 new 없이 호출할 경우 error가 발생합니다.

  • 클래스 내의 모든 코드에는 암묵적으로 strict mode가 지정되어 실행되며 strict mode를 해제할 수 없습니다.

  • 클래스 내의 메서드 및 정적 메서드는 모두 [[Enumable]]이 false 입니다.

  • 클래스를 통해 상속을 구현한다면, 부모 클래스와 자식 클래스의 인스턴스 프로토타입 체인뿐만 아니라 클래스간의 프로토타입 체인도 생성합니다.




이터레이션 프로토콜

 

  • ES6에서는 순회 가능한 데이터 컬렉션을 이터레이션 프로토콜을 준수하는 이터러블로 통일하여 for...of문, 스프레드 문법, 배열 디스트럭처링 할당의 대상으로 사용할 수 있도록 일원화했습니다. 이터레이션 프로토콜에는 이터러블 프로토콜과 이터레이터 프로토콜이 있습니다.




이터러블 프로토콜(iterable protocol)

 

  • Well-known Symbol인 Symbol.iterator를 프로퍼티 키로 사용한 메서드를 직접 구현하거나 프로토타입 체인을 통해 상속 받은 Symbol.iterator 메서드를 호출하면 이터레이터 프로토콜을 준수한 이터레이터를 반환합니다. 이러한 규약을 이터러블 프로토콜이라 하며, 이터러블 프로토콜을 준수한 객체를 이터러블이라 합니다. 이터러블은 for...of 문으로 순회할 수 있으며 스프레드 문법과 배열 디스트럭처 할당의 대상으로 사용할 수 있습니다.




이터레이터 프로토콜(iterator protocol)

 

  • 이터러블의 Symbol.iterator 메서드를 호출하면 이터레이터 프로토콜을 준수한 이터레이터를 반환합니다.
    이터레이터는 next 메서드를 소유하며 next 메서드를 호출하면 이터러블을 순회하며 value와 done프로퍼티를 갖는 Iterator Result Object를 반환합니다. 이러한 규약을 이터레이터 프로토콜이라 하며, 이터레이터 프로토콜을 준수한 객체를 이터레이터라 합니다. 이터레이터는 이터러블의 요소를 탐색하기 위한 포인터 역할을 합니다.




이터러블

 

const isIterable = (v) => console.log(typeof v[Symbol.iterator] === "function");

isIterable([]); // true
isIterable(""); // true
isIterable(new Map()); // true
isIterable(new Set()); // true
isIterable({}); // false

 

const array = [1, 2, 3];

for (const item of array) {
  console.log(iter);
}

console.log([...array]);

 

  • 이터러블 프로토콜을 준수한 객체를 이터러블이라 합니다. 즉, 이터러블은 Symbol.iterator를 프로퍼티 키로 사용한 메서드를 직접 구현하거나 프로토타입 체인을 통해 상속받은 객체를 말합니다. 이터러블은 for...of 문으로 순회할 수 있으며, 스프레드 문법과 배열 디스트럭처링 할당의 대상으로 사용할 수 있습니다.




이터레이터

 

const array = [1, 2, 3];

const iterator = array[Symbol.iterator];

console.log(iterator.next()); // [value: 1, done: false]
console.log(iterator.next()); // [value: 2, done: false]
console.log(iterator.next()); // [value: 3, done: false]
console.log(iterator.next()); // [value: undefined, done: true]

 

  • 이터러블의 Symbol.iterator 메서드를 호출하면 이터레이터 프로토콜을 준수한 이터레이터를 반환합니다 이터러블의 Symbol.iterator 메서드가 반환한 이터레이터는 next 메서드를 갖습니다. next 메서드를 호출하면 이터러블을 순차적으로 한 단계씩 순회하며 순회 결과를 나타내는 iterator result object를 반환합니다.




빌트인 이터러블

 

빌트인 이터러블
Symbol.iterator 메서드
Array Array.prototype[Symbol.iterator]
String String.prototype[Symbol.iterator]
Map Map.prototype[Symbol.iterator]
Set Set.prototype[Symbol.iterator]
TypedArray TypedArray.prototype[Symbol.iterator]
arguments arguments[Symbol.iterator]

 

  • 자바스크립트는 이터레이션 프로토콜을 준수한 객체인 빌트인 이터러블을 제공합니다. 위 표에 나와있는 표준 빌트인 객체들은 빌트인 이터러블입니다.




for...of 문

 

  • for...of 문은 이터러블을 순회하면서 이터러블의 요소를 변수에 할당합니다. for...of문과 for...in 문은 다르며 for...in문은 객체의 프로토타입 체인 상에 존재하는 모든 프로토타입의 프로퍼티 중에서 프로퍼티 어트리뷰트가 [[Enumerable]]의 값이 true인 프로퍼티를 순회하며 열거합니다.
    for...of문은 내부적으로 이터레이터의 next 메서드를 호출하여 이터러블을 순회하며 enxt 메서드가 반환한 iterator result object의 value 프로퍼티 값을 할당하는 식으로 처리하고 done 프로퍼티 값이 false이면 이터러블의 순회를 계속하고 true이면 이터러블의 순회를 중단합니다.




이터러블과 유사 배열 객체

 

const arrayList = {
  0: 1,
  1: 2,
  2: 3,
  length: 3,
};

 

  • 유사 배열 객체는 마치 배열처럼 인덱스로 프로퍼티 값에 접근할 수 있고 length 프로퍼티를 갖는 객체를 말합니다.

 

  • 유사 배열 객체라고 해서 무조건 이터러블 객체는 아닙니다. Symbol.iterator 프로퍼티를 이용해서 이터레이션 프로토콜을 준수하는 메서드를 구현해야 합니다.




자바스크립트 배열이란?


const arr = [1, 2, 3];

arr.constructor === Array;
Object.getPrototypeOf(arr) === Array.prototype;

  • 배열이란 인덱스에 대응하는 데이터들로 이루어진 자료구조를 말합니다.

  • 자바스크립트에서는 배열 타입이 별도로 존재하지 않으며 배열은 객체입니다. 배열은 배열 리터럴, Array 생성자 함수, Array of, Array.from 메서드로 생성할 수 있습니다.




자바스크립트 배열의 특징


const arr = [, 2, , 4];

// [empty, 2, empty, 3] 출력
console.log(arr);

// 4 출력
console.log(arr.length);

  • 자바스크립트 배열은 해시 테이블로 구현된 객체이므로 인덱스로 요소에 접근하는 경우 일반적인 배열보다 성능적인 면에서 떨어지지만 요소를 삽입, 삭제하는 경우에는 일반적인 배열보다 빠른 성능을 기대할 수 있습니다. 자바스크립트는 배열의 중간 요소를 비울 수 있는 희소 배열을 문법적으로 허용합니다.
    희소 배열은 연속적인 값의 집합이라는 배열의 기본적인 개념과 맞지 않으며, 성능에도 좋지 않은 영향을 줍니다.




모던 자바스크립트 배열


  • 최적화가 잘 되어 있는 모던 자바스크립트 엔진은 요소의 타입이 일치하는 배열을 생성할 때 일반적인 의미의 배열처럼 연속된 메모리 공간을 확복합니다. 배열을 생성할 때 희소 배열을 생성하지 않도록 주의하고, 배열에는 같은 타입의 요소를 연속적으로 위치시키는 것이 최선입니다.




배열 생성 방법

// 배열 리터럴
let arr = [1, 2, 3];

// length 5개인 배열 생성
arr = new Array(5);

// [1,2,3] 요소를 가진 배열 생성
arr = new Array(1, 2, 3);

// 요소가 1인 배열 생성
arr = Array.of(1);

// 유사 배열 객체, 이터러블로 배열 생성
arr = Array.from({ length: 2, 0: "a", 1: "b" });

arr = Array.from("Hello");

  • Array.of, Array.from은 ES6에 추가된 배열 생성 방법입니다.




유사 배열 객체(array-like object)


  • 유사 배열 객체는 마치 배열처럼 인덱스로 프로퍼티 값에 전급할 수 있고 length 프로퍼티를 갖는 객체를 말합니다.




이터러블(iterable object)


  • 이터러블 객체는 Symbol.iterator 메서드를 구현하여 for...for 문으로 순회할 수 있으며, 스프레드 배열 디스트럭처링 할당의 대상으로 사용할 수 있는 객체를 말합니다.




배열 요소 추가와 삭제


const arr = [20, 30, 40];

// 뒤에 요소 추가
arr.push(100);

// 뒤에 요소 삭제
arr.pop();

// 배열 요소 삭제
delete arr[0];

arr.splice(0, 1);

// [30, 40] 출력
console.log(arr);

  • 배열은 객체이며 배열의 특정 요소를 삭제하기 위해서는 delete 연산자를 사용할 수 있습니다. 하지만, 이때 희소배열이 되며 length 프로퍼티 값은 변하지 않습니다. 그렇기 때문에 splice 메서드를 사용하는 것이 더 좋습니다.




모듈(module)이란?


  • 모듈이란 애플리케이션을 구성하는 개별적 요소로서 재사용이 가능한 코드 모음을 말합니다. Javascript에서의 모듈은 기능을 기준으로 파일 단위로 분리합니다. 이때 모듈이 성립하려면 모듈은 자신만의 파일 스코프(모듈 스코프)를 가질 수 있어야 합니다.




모듈 export


export const hello = () => {
  console.log("Hello World");
};

  • 자신만의 모듈(파일) 스코프를 갖는 모듈 내부에 있는 코드들은 기본적으로 비공개 상태입니다. 하지만, 모듈안에 있는 기능을 사용자가 사용하거나 다른 모듈에서 사용하기 위해서는 선택적으로 공개할 수 있어야 합니다. 이렇게 일부 코드를 공개하기 위해서는 공개할 코드에 export 키워드를 사용하고 다른 모듈에서는 사용할 외부 모듈의 코드에 대해서 import하여 해당 코드를 접근할 수 있도록 할 수 있습니다.




브라우저와 모듈 시스템


  • 자바스크립트는 웹 페이지의 보조적인 역할을 목적으로 태어났기 때문에 다른 일반 프로그래밍 언어보다 지원하는 기능이 많지 않았습니다. 그래서 모듈 시스템이 지원되지 않았고 브라우저에서 각 파일로 분리된 자바스크립트 파일을 script 태그로 불러와도 하나의 파일처럼 동작하기 때문에 전역 코드의 오염이 발생되는 경우가 많았습니다.(Node.js는 모듈 시스템을 지원하고 있습니다.)




브라우저에서 모듈 시스템 사용하기


<!DOCTYPE html>
<html>
  <body>
    <script type="module" scr="foo.mjs"></script>
    <script type="module" scr="bar.mjs"></script>
  </body>
</html>

  • ES6 이후 부터는 브라우저에서도 모듈 시스템을 사용할 수 있으며, 모듈로서 사용할 파일의 확장자 이름은 .mjs로 해야합니다. 그리고 script 태그의 속성으로 type="module"을 지정하면됩니다.




'Programming Language > JavaScript' 카테고리의 다른 글

Javascript의 이터레이션 프로토콜이란?  (0) 2022.12.20
Javascript 배열  (0) 2022.12.20
Javascript의 async/await 사용법  (0) 2022.12.19
Javascirpt fetch 사용 방법  (0) 2022.12.19
Javascript의 Promise란?  (0) 2022.12.19

async/await


  • ES8에 도입된 async/await은 Promise를 기반으로 동작하여 가독성 좋게 비동기 처리를 동기처럼 보이도록 구현할 수 있습니다.




async/await 사용법


const fetchTodo = async () => {
  const res = await fetch(url);
  const todo = await res.json();
  console.log(todo);
};

fetchTodo();

  • 위와 같이 Promise의 then과 같은 후속 처리 메서드를 호출할 필요없이 마치 동기처럼 보이도록 구현할 수 있습니다.




async 함수


async function foo(n) {
  return n;
}
foo(1).then((res) => console.log(res)); // return 1

const bar = async function (n) {
  return n;
};
bar(2).then((res) => console.log(res)); // return 2

const baz = async (n) => n;
baz(3).then((res) => console.log(res)); // return 3

const obj = {
  async foo(n) {
    return n;
  },
};
obj.foo(4).then((res) => console.log(res));

class MyClass {
  async bar(n) {
    return n;
  }
}
const myClass = new MyClass();
myClass.bar(5).then((res) => console.log(res));

  • await 키워드는 반드시 async 함수 내부에서 사용해야 합니다. async 함수는 async 키워드를 사용해 정의하며 언제나 프로미스를 반환합니다. async 함수가 명시적으로 프로미스를 반환하지 않더라도 async 함수는 암묵적으로 반환값을 resolve하는 프로미스를 반환합니다.

  • 클래스의 constructor 메서드는 async 메서드가 될수 없습니다. 클래스의 constructor 메서드는 인스턴스를 반환해야 하지만 async 함수는 언제나 프로미스를 반환해야 하기 때문입니다.




await 키워드


(async () => {
  const res = await fetch(url);
  console.log(res.status);
})();

  • await 키워드는 Promise가 settled 상태(비동기 처리가 수행된 상태)가 될 때까지 대기하다가 settled 상태가 되면 Promise가 resolve한 처리 결과를 반환합니다. await 키워드는 반드시 Promise 앞에 사용해야 합니다.




await 키워드 사용시 주의할 점


const foo = async () => {
  const a = await new Promise((resolve) => setTimeout(() => resolve(1), 3000));
  const b = await new Promise((resolve) => setTimeout(() => resolve(2), 1000));
  const c = await new Promise((resolve) => setTimeout(() => resolve(3), 1000));
  console.log("Hello Wolrd");
};

// 약 6초 소요
foo();
console.log("finish");

const foo = async () => {
  const res = await Promise.all([
    new Promise((resolve) => setTimeout(() => resolve(1), 3000)),
    new Promise((resolve) => setTimeout(() => resolve(2), 1000)),
    new Promise((resolve) => setTimeout(() => resolve(3), 1000)),
  ]);

  console.log(res);
};

// 약 3초 소요
foo();
console.log("finish");

  • foo 함수를 호출할 경우 await으로 인해 6초 이후 "Hello World"가 출력됩니다. 즉, 위와 같이 각각의 Promise가 서로 연관되지 않고 처리 순서를 지킬 필요가 없다면은 일일이 await을 거는 것보다는 Promise.all을 이용해서 한번에 요청 후 요청한 비동기 요청이 완료되었을 때 응답을 처리하는 것이 좋습니다.




에러 핸들링


(async () => {
  try {
    const res = await fetch(url);
  } catch (err) {
    console.log(err);
  }
})();

  • Prmoise를 후속 처리 메서드로 처리할 경우 try/catch로 에러 핸들링하기 적합하지 않습니다. 하지만, async/await에서 에러 처리는 try/catch를 사용하기에 적합합니다.

  • async 함수 내에서 err가 발생되었을 경우 에러를 reject하는 Promise를 반환합니다. 그렇기 때문에 async 함수 외부에서 .catch 후속 처리 메서드로 에러를 핸들링 할 수 있습니다.




'Programming Language > JavaScript' 카테고리의 다른 글

Javascript 배열  (0) 2022.12.20
자바스크립트의 모듈(module)이란?  (0) 2022.12.19
Javascirpt fetch 사용 방법  (0) 2022.12.19
Javascript의 Promise란?  (0) 2022.12.19
JSON(Javascript Object Notation)이란?  (0) 2022.12.19

fetch


fetch(url).then((res) => console.log(res));

  • fetch 함수는 Promise 방식을 지원하고 HTTP request 기능을 제공하는 함수입니다. fetch 함수는 HTTP 응답을 나타내는 Response 객체를 래핑한 Promise 객체를 반환합니다. 그리고 res 객체에는 HTTP 응답을 나타내는 다양한 프로퍼티를 제공합니다.

  • featch 에러는 서버로부터 온 응답이 404 또는 500이여도 rejected 상태가 되지 않고 fulfilled 상태가 됩니다. rejected 상태가 되는 경우는 네트워크 장애나 CORS 에러에 의해 요청이 완료되지 못한 경우에는 Promise를 rejected 합니다.




fetch 사용 예시


fetch(url).then((res) => {}); // method를 설정하지 않으면 GET으로 정의합니다.

fetch(url, {
  method: "POST", // or PUT, PATCH
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(payload),
}).then((res) => {});

fetch(url, { method: "DELETE" }).then((res) => {});



// async/await 을 사용한 버전

(async () => {
  const res = await fetch(url);
})();

(async () => {
  fetch(url, {
    method: "POST", // or PUT, PATCH
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(payload),
  });
})();

(async () => {
  fetch(url, { method: "DELETE" }).then((res) => {});
})();




콜백으로 인한 비동기 처리의 단점

 

콜백 지옥(Callback hell)

 

function fn() {
  setTimeout(() => {
    console.log("하나");
    setTimeout(() => {
      console.log("둘");
      setTimeout(() => {
        console.log("셋");
      }, 0);
    }, 0);
  }, 0);
}
fn(); // 결과 순서 => '하나', '둘', '셋'

 

  • ES6 이전에는 콜백 방식을 이용해서 비동기 처리를 하였습니다. 하지만, 콜백 방식으로 비동기 처리를 할 경우 비동기 처리에 대한 결과를 확인하고 또 다시 비동기 처리 요청하는 과정에서 가독성이 나빠지고 에러의 처리가 힘들어지게 됩니다. 즉, 콜백 지옥에 빠지게 됩니다. ES6에서는 이러한 단점을 보완하기 위해서 Promise 방식을 도입했습니다.




에러 처리의 한계

 

try {
  setTimeout(() => {
    throw new Error("Error!");
  }, 1000);
} catch (err) {
  console.error("catch", e);
}

 

  • 비동기 처리를 위한 콜백 패턴의 문제점 중 하나로는 에러 처리가 곤란하다는 것입니다. setTimeout으로 전달된 콜백 함수는 호출자가 setTimeout 함수가 아닙니다. 비동기 처리방식에 따라서 추후 이벤트 루프가 실행 컨텍스트 스택에 push되어 실행되는데 따라서 콜백 함수가 발생시킨 에러는 setTimeout을 감싼 catch 블록에서 캐치되지 않습니다.




Promise

 

  • 콜백 방식으로 처리할 경우 위와 같은 단점이 있기 때문에 ES6에서는 콜백 방식이 아닌 Promise 방식을 통해 비동기 처리를 구현할 수 있습니다.




Prmoise 생성

 

const promise = new Promise((resolve, reject) => {
  // 비동기 처리
  if (true) {
    resolve(true);
  } else {
    reject(false);
  }
});

 

  • Promise는 ES6에 도입된 ECMAScript 사양에 정의된 표준 빌트인 객체입니다. Promise 생성자 함수는 비동기 처리를 수행할 콜백 함수를 인수로 전달받는데 이 콜백 함수는 resolve와 reject 함수를 인수로 전달받습니다.

 

  • 비동기 처리를 위해 콜백 함수를 정의할 때 결과에 대한 응답을 하기 위해 매개변수로 resolve, reject를 받도록 정의합니다. 그리고 Promise 생성자 함수의 인자로 전달합니다. 처리 성공 시 결과와 함께 resolve를 호출하고, 실패 시 결과와 함께 reject를 호출하면 됩니다.




Promise 상태와 결과

 

Promise 상태

 

프로미스의 상태 정보
의미
상태 변경 조건
pending 비동기 처리가 아직 수행되지 않은 상태 프로미스가 생성된 진후 기본 상태
fulfilled 비동기 처리가 수행된 상태(성공) resolve 함수 호출
rejected 비동기 처리가 수행된 상태(실패) reject 함수 호출

 

  • Poromise는 위와 같이 현재 비동기 처리가 어떻게 진행되고 있는지를 나타내는 상태(status) 정보를 갖습니다. 생성된 직후의 Promise는 기본적으로 pending 상태입니다. 이후 비동기 처리가 수행되면 비동기 처리 결과에 따라 fulfilled 또는 rejected 상태가 됩니다. 그리고 fulfilled, rejected 상태를 settled 상태라고 합니다.




Promise 처리 결과

 

  • Promise 처리 후 결과는 [[PromiseStatus]], [[PromiseResult]] 내부 슬롯에 저장됩니다.




Promise의 후속 처리 메서드

 

  • Promise 비동기 처리 상태가 변화하면 이에 따른 후속 처리를 할 수 있습니다. 예를들어 Promise의 상태가 fulfilled, rejected 냐에 따라서 후속 처리해야 할 로직이 다른데, 이를 위해서 Promise는 then, catch, finally 메서드를 제공합니다.

 

  • Promise의 비동기 처리 상태가 변화하면 후속 처리 메서드에 인수로 전달한 콜백 함수가 선택적으로 호출됩니다. 그리고 Promise 처리결과 또한 콜백 함수의 인자로 전달됩니다. 모든 후속 처리 메서드는 Promise를 반환하며, 비동기로 동작합니다.




Promise.prototype.then

 

const t = new Promise((resolve, reject) => resolve("Hello"));

t.then(
  (result) => console.log("fulfilled"),
  (result) => console.log("rejected")
);

 

  • then 메서드는 두 개의 콜백 함수를 인자로 받으며 첫 번째 인자는 fulfilled 상태가 되었을 때, 호출할 콜백 함수를 두 번째 인자는 rejected 상태가 되었을 때 호출할 콜백 함수를 의미합니다.




promise.prototype.catch

 

const t = new Promise((resolve, reject) => resolve("Hello"));

t.then((result) => console.log("fulfilled")).catch((result) =>
  console.log("rejected")
);

 

  • catch 메서드는 한 개의 콜백 함수를 인수로 전달받습니다. catch 메서드의 콜백 함수는 Promise가 rejected 상태인 경우만 호출됩니다. 그리고 then과 연계해서 사용할 수 있습니다.




promise.prototype.finally

 

const t = new Promise((resolve, reject) => resolve("Hello"));

t.then((result) => console.log("fulfilled"))
  .catch((result) => console.log("rejected"))
  .finally(() => console.log("finally"));

 

  • finally 메서드는 한 개의 콜백 함수를 인수로 전달 받으며 Promise의 성공, 실패 여부와 상관없이 무조건 한 번 호출됩니다. finally 메서드는 try/catch에서의 finally와 같이 상태와 상관없이 공통적으로 수행해야 할 처리 내용이 있을 때 유용합니다.




Promise의 에러 핸들링

 

  • Promise에서 에러처리는 then 메서드의 두 번째 인자로 전달된 콜백 함수 또는 catch 메서드에 인자로 전달된 콜백 함수를 통해서 에러 핸들링을 할 수 있습니다.




Promise 체이닝

 

const t = new Promise((resolve, reject) => resolve("Hello"));

t.then((result) => {
  return new Promise((resolve, reject) => resolve(`${result} World`));
})
  .then((result) => console.log(result))
  .finally(() => console.log("finally"));

 

  • 콜백 함수를 이용한 비동기 처리는 비동기 처리 결과에 따른 콜백 함수가 중첩될수록 가시성이 매우 떨어집니다.

 

  • 콜백 지옥의 문제를 Promise와 Promise 메서드를 이용해서 위 코드와 같이 이전 비동기 처리 결과에 따른 비동기 후속 처리를 다시 요청 후 Promise 메서드를 통해 결과를 처리할 수 있습니다. 이를 Promise 체이닝이라고 합니다.

 

  • 위와 같은 처리가 가능한 이유는 비동기 후속 처리를 위한 Promise 메서드 내부에서 Promise가 아닌 값을 반환하더라도 그 값을 암묵적으로 resolve하여 프로미스를 생성해 반환합니다. 그리고 반환된 Promise를 통해서 Promise 후속 처리 메서드를 호출하여 체이닝을 통해 비동기 처리 결과를 처리할 수 있습니다.




마이크로테스크 큐

 

setTimeout(() => console.log(1), 0);

Promise.resolve()
  .then(() => console.log(2))
  .then(() => console.log(3));

 

  • Promise의 후속 처리 메서드도 비동기로 동작하므로 1 -> 2 -> 3의 순으로 출력될것 같지만 2 -> 3 -> 1 순서로 출력됩니다. 그 이유는 Promise의 후속 처리 메서드의 콜백 함수는 테스크 큐가 아니라 마이크로테스크 큐에 저장되기 때문입니다. 마이크로테스크 큐는 테스크 큐보다 우선순위가 높습니다. 그렇기 때문에 이벤트 루프는 콜 스택이 비면 먼저 마이크로테스크 큐에서 대기하고 있는 함수를 가져와서 실행 컨텍스트 스택에 push하며 마이크로테스트 큐가 비었을 때 테스크 큐에서 대기하고 있는 함수를 가져와 실행합니다.




'Programming Language > JavaScript' 카테고리의 다른 글

Javascript의 async/await 사용법  (0) 2022.12.19
Javascirpt fetch 사용 방법  (0) 2022.12.19
JSON(Javascript Object Notation)이란?  (0) 2022.12.19
Javascript의 비동기 처리 방식  (0) 2022.12.19
Set과 Map  (0) 2022.12.19

JSON(Javascript Object Notation)이란?


  • JSON(Javascript Object Notation)은 Javascript Object 객체 표현 방식으로 데이터를 표기하는 포맷입니다.




JSON 표기방식


{
  "name": "devhun",
  "age": "25",
  "isHandsome": true,
  "body": ["traveling", "tennis"]
}

  • JSON 표기법은 위와 같으며 key에는 반드시 큰따옴표로 묶어야합니다.




JSON.stringify


const player = {
  name: "devhun",
  age: "25",
  isHandsome: true,
  body: ["traveling", "tennis"],
};

const jsonStr = JSON.stringify(player);

  • JSON.stringify는 객체를 JSON 포맷의 문자열로 변환하는 작업을 수행합니다.




JSON.parse


  • JSON 포맷의 문자열을 객체로 변환해줍니다. 예를들어서 서버로 부터 받은 JSON 포맷의 문자열을 클라이언트가 JSON.parse를 통해서 다시 객체로 변환하여 사용할 수 있습니다.




'Programming Language > JavaScript' 카테고리의 다른 글

Javascirpt fetch 사용 방법  (0) 2022.12.19
Javascript의 Promise란?  (0) 2022.12.19
Javascript의 비동기 처리 방식  (0) 2022.12.19
Set과 Map  (0) 2022.12.19
자바스크립트 Symbol이란?  (0) 2022.12.19

자바스크립트 엔진과 싱글 쓰레드

 

  • 자바스크립트 엔진은 한 번에 하나의 태스크만 실행할 수 있는 싱글 쓰레드 방식으로 동작합니다. 싱글 쓰레드 방식으로 동작하기 때문에 한번에 하나의 태스크만 실행할 수 있습니다. 하지만 브라우저와 Node.js와 같이 백그라운드에서는 멀티 쓰레드로 동작합니다.




이벤트 루프와 테스크 큐

 

이미지 출처 :&nbsp;https://velog.io/@titu/JavaScript-Task-Queue%EB%A7%90%EA%B3%A0-%EB%8B%A4%EB%A5%B8-%ED%81%90%EA%B0%80-%EB%8D%94-%EC%9E%88%EB%8B%A4%EA%B3%A0-MicroTask-Queue-Animation-Frames-Render-Queue



  • 자바스크립트의 특징 중 하나는 싱글 쓰레드로 동작한다는 것입니다. 자바스크립트는 콜 스택과 힙으로 구성된 자바스크립트 엔진, 이벤트 루프, 매크로 테스크 큐, 마이크로 테스크 큐를 통해 동시성을 제공합니다.

 

  • 비동기 방식으로 동작하는 setTimeout의 콜백 함수의 평가와 실행은 자바스크립트 엔진이 담당하지만 호출 스케줄링을 위한 타이머 설정과 콜백 함수의 등록은 실행 환경인 브라우저 또는 Node.js가 담당합니다.



마이크로테스크 큐

 

setTimeout(() => console.log(1), 0);

Promise.resolve()
  .then(() => console.log(2))
  .then(() => console.log(3));

 

  • Promise의 후속 처리 메서드도 비동기로 동작하므로 1 -> 2 -> 3의 순으로 출력될것 같지만 2 -> 3 -> 1 순서로 출력됩니다. 그 이유는 Promise의 후속 처리 메서드의 콜백 함수는 테스크 큐가 아니라 마이크로테스크 큐에 저장되기 때문입니다. 마이크로테스크 큐는 테스크 큐보다 우선순위가 높습니다. 그렇기 때문에 이벤트 루프는 콜 스택이 비면 먼저 마이크로테스크 큐에서 대기하고 있는 함수를 가져와서 실행 컨텍스트 스택에 push하며 마이크로테스트 큐가 비었을 때 테스크 큐에서 대기하고 있는 함수를 가져와 실행합니다.



 

자바스크립트의 비동기 처리 과정

 

function foo() {
  console.log("foo");
}

function bar() {
  console.log("bar");
}

setTimeout(foo, 0);
bar();

 

  1. 전역 코드가 평가되어 전역 실행 컨텍스트가 생성되고 콜 스택에 푸시됩니다.

  2. 전역 코드가 실행되기 시작하여 setTimeout 함수가 호출됩니다. 이때 setTimeout 함수의 함수 실행 컨텍스트가 생성되고 콜 스택에 푸시되어 현재 실행중인 컨텍스트가 됩니다. 그리고 브라우저 또는 Node.js의 호스트 객체 타이머 함수도 함수이므로 함수 실행 컨텍스트를 생성합니다.

  3. setTimeout 함수가 실행되면 콜백 함수를 호출 스케줄링하고 종료되어 콜 스택에서 팝됩니다, 즉 타이머 설정과 타이머가 만료되면 콜백 함수를 테스크 큐에 푸시하는 것은 브라우저 또는 Node.js의 역할입니다.

  4. 브라우저 또는 Node.js가 설정한 타이머의 만료를 기다리면서 자바스크립트 엔진은 현재 실행 컨텍스트 스택에 있는 bar에 대한 실행 컨텍스트를 수행합니다.

  5. bar가 수행이 만료되어 실행 컨텍스트 스택이 비어있고 타이머 또한 만료되어 브라우저 또는 Node.js가 테스크 큐에 foo 함수가 enqueue된 상태라면은 이벤트 루프가 이를 확인하여 실행 컨텍스트 스택에 push합니다.

  6. 실행 컨텍스트 스택에 foo 실행 컨텍스트가 push되면 자바스크립트 엔진은 이를 확인하여 해당 실행 컨텍스트를 실행합니다.




'Programming Language > JavaScript' 카테고리의 다른 글

Javascript의 Promise란?  (0) 2022.12.19
JSON(Javascript Object Notation)이란?  (0) 2022.12.19
Set과 Map  (0) 2022.12.19
자바스크립트 Symbol이란?  (0) 2022.12.19
ES6에서의 함수  (0) 2022.12.19

Set 자료구조란?

 

구분
배열
Set 객체
동일한 값을 중복하여 포함할 수 있다. O X
요소 순서에 의미가 있다. O X
인덱스로 요소에 접근할 수 있다. O X

 

  • Set 객체는 중복되지 않는 유일한 값을 저장하는 해시 테이블 자료구조입니다. Set 객체는 배열과 유사하지만 위와 같은 차이가 있습니다.




Set 사용법

 

const set = new Set([1, 2, 3, 4]);

set.add(5).add(4);

// true return
set.delete(1);

console.log(set);

 

  • Set 생성자 함수는 이터러블을 인수로 전달받아 Set 객체를 생성합니다. 이때 이터러블의 중복된 값은 Set 객체에 요소로 저장되지 않습니다. 중복을 허용하지 않는 Set 객체의 특성을 활용하여 배열에서 중복된 요소를 제거할 수 있습니다.

 

  • add를 통해서 요소를 추가할 수 있으며, 중복된 요소가 추가될 경우 무시됩니다. NaN === NaN은 false를 return 하지만 Set에서는 이를 동일하다고 평가합니다.

 

  • delete는 요소를 삭제할 때 사용하는 함수이며 return 값은 삭제 성공 여부에 다라서 true, false를 return 합니다.




Map 자료구조란?

 

구분
객체
Map 객체
키로 사용할 수 있는 값 문자열 또는 심벌 값 객체를 포함한 모든 값
이터러블 X O
요소 개수 확인 Object.keys(obj).length map.size
  • Map 객체는 키와 값의 쌍으로 이루어진 해시 테이블 자료구조 입니다. Map 객체는 객체와 유사하지만 위와 같은 차이가 있습니다.




Map 사용법

 

const map = new Map([
  ["key1", "value1"],
  ["key2", "value2"],
]);

map.set("key3", "value3").set("key1", "Hello");

map.get("key3");

// return 값은 boolean
map.delete("key1");

console.log(map);

 

  • Map 생성자 함수는 이터러블을 인수로 전달받아 Map 객체를 생성합니다. 이때 인수로 전달되는 이터러블은 키와 값의 쌍으로 이루어진 요소로 구성되어야 합니다. Map 생성자 함수의 인수로 전달한 이터러블에 중복된 키를 갖는 요소가 존재하면 값이 덮어씌워집니다. 따라서 Map 객체에는 중복된 키를 갖는 요소가 존재할 수 없습니다.

 

  • set 메서드를 통해서 요소를 추가할 수 있으며 추가된 Map 객체를 return합니다.

 

  • get 메서드를 통해서 key에 대응하는 value를 얻을 수 있으며 key가 없을 경우 undefined를 return 합니다.

 

  • Map 또한 Set과 동일하게 NaN === NaN을 true로 평가합니다. 객체의 키로는 제한이 있지만 Map 객체의 키 타입에는 제한이 없으며 객체를 포함한 모든 값을 키로 사용할 수 있습니다.




'Programming Language > JavaScript' 카테고리의 다른 글

JSON(Javascript Object Notation)이란?  (0) 2022.12.19
Javascript의 비동기 처리 방식  (0) 2022.12.19
자바스크립트 Symbol이란?  (0) 2022.12.19
ES6에서의 함수  (0) 2022.12.19
자바스크립트와 클래스  (0) 2022.12.15

+ Recent posts