DAY - 18

공부 저장소·2021년 10월 7일

Class

객체 생성

ES6에서 추가된 기능이며 생성자 함수처럼 객체를 생성하기 위한 템플릿으로써 작용한다.

우선 객체를 생성하는 기본 문법을 보겠다.

const User = function (name, age) {
  this.name = name;
  this.age = age;
  this.showName = function () {
    console.log(this.name);
  };
};

//User.prototype.showName = function () {
//  console.log(this.name);
//}; 아래 생성자 Class처럼 프로토타입에 메소드를 저장시킬 경우

const Mike = new User('Mike', 26);
console.log(Mike);
//User { name: 'Mike', age: 26, showName: [Function (anonymous)] }
Mike.showName();
//Mike

이는 기존의 배웠던 방식대로 생성자 함수를 이용하여 객체를 생성한 모습이다.

이 번엔 Class를 이용하여 객체를 생성 해보겠다.

class User2 {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  showName() {
    console.log(this.name);
  }
}

const Tom = new User2('Tom', 28);
console.log(Tom);
//User2 { name: 'Tom', age: 28 }
Tom.showName();
//Tom

객체 생성시에 new를 붙이는 것은 생성자 함수와 같은 방식이다.

하지만 Class 내부생성자 함수와 다른 모습이다.

construct는 객체를 만들어 주는 생성자 메소드이다.
인수를 받아 객체를 초기화 하고 데이터에 값을 할당을 하는 역할을 하고 객체 내의 메소드 함수생성자 함수처럼 해당 객체 내부에 메소드를 저장하는 것이 아닌 프로토타입 내부에 저장시킨다.

때문에 Class를 이용하여 생성된 객체를 출력시켰을 때 메소드가 보이지 않지만 실행은 가능한 이유이다.

상속

extends를 이용하여 다른 객체 생성 Class를 상속할 수 있다.

class Car {
  construct(color) {
    this.color = color;
    this.wheels = 4;
  }
  drive() {
    console.log('drive..');
  }

  stop() {
    console.log('STOP !!');
  }
}

class Bmw extends Car {
  park() {
    console.log('PARK ~');
  }
  stop() {
    console.log('멈춥니다.');
  }
}

const z4 = new Bmw('black');

z4.drive();	//drive..
z4.stop();	//멈춥니다.
//stop은 Bmw Class에서 자식 Class인 Car의 stop(); 메소드를 덮어 씌웠기 때문에 'STOP !!'이 아닌 '멈춥니다.'가 출력된다.
z4.park();	//PARK ~

오버라이딩

메소드 오버라이딩

class Car {
  construct(color) {
    this.color = color;
    this.wheels = 4;
  }
  drive() {
    console.log('drive..');
  }

  park() {
    console.log('PARK ~');
  }
}

class Bmw extends Car {
  stop() {
    console.log('멈춥니다.');
  }
  park() {
    super.park();
    console.log('띠리리리 띠리리리리');
  }
}

const z4 = new Bmw('black');

z4.drive();	//drive..
z4.stop();	//멈춥니다.
z4.park();	//PARK ~
		//띠리리리 띠리리리리
//park는 super.park();를 이용하여 자식 클래스인 Car Class의 park(); 메소드를 사용하고 그 다음 console.log로 워딩을 출력한다.

생성자 오버라이딩

부모 Class에서 생성된 값을 가져오려면 부모 생성자를 호출해야 한다.

잘못된 예를 먼저 보겠다.

class Car {
  constructor(color) {
    this.color = color;
    this.wheels = 4;
  }
  drive() {
    console.log('drive..');
  }

  stop() {
    console.log('STOP !!');
  }
  park() {
    console.log('PARK ~');
  }
}

class Bmw extends Car {
  constructor() {
    this.navigation = 1;
  }
}

const z4 = new Bmw('black');

console.log(z4);
//Error

이렇게 정상적으로 자식 Class에서 생성된 값을 못 가져오는 모습을 볼 수 있다.

이유는 extends를 이용하여 만든 Class는 자식 객체가 있다는 이유로 빈 객체를 생성하고 초기화 하는 단계를 건너뛰기 때문과 부모Class에서 자식Class로 인자가 전달되지 않기 때문이다.
아래와 같이 해결하도록 하자.

class Car {
  constructor(color) {
    this.color = color;
    this.wheels = 4;
  }
  drive() {
    console.log('drive..');
  }

  stop() {
    console.log('STOP !!');
  }
  park() {
    console.log('PARK ~');
  }
}

class Bmw extends Car {
  constructor(color) {//인자를 받아서
    super(color);// 자식 Class에 인자를 전달하여 정상적으로 자식 Class에서 값을 생성할 수 있도록 함.
    this.navigation = 1;
  }
}

const z4 = new Bmw('black');

console.log(z4);
//Bmw { color: 'black', wheels: 4, navigation: 1 }

정상적으로 자식 Class에서 생성된 값을 가져올 수 있다.

Promise

const pr = new Promise((resolve, reject)=>{
 	//resolve = 성공했을 때의 실행하는 함수
   	//reject = 실패했을 때의 실행하는 함수
  
  
	//code . . . 
});

위의 어떤 일이 완료(성공 or 실패) 됐을 때의 실행되는 함수를 callback 함수라고 한다.

Promise 함수stateresult라는 프로퍼티를 기본으로 갖는다.
이는 처음에 함수가 생성될 때는 각각 state는 pending 즉 대기하는 값을 가지고 있고 result는 정의되지 않은 undefined 값을 가지고 있는다.

성공 즉 resolve가 호출되면 이 프로미스 함수의 state는 fulfilled 이행됐다는 값으로 바뀌고 result는 value 값을 가진다.

반대로 실패 즉 reject가 호출되면 프로미스 함수의 state는 rejected 거부됐다는 값으로 바뀌고 result는 error 값을 가진다.

아래와 같은 예시로

const pr = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('OK');
  }, 3000);
});

pr.then(
  function (result) {
    console.log(result + '!, 가지러 가자');
  },
  function (err) {
    console.log('다시 주문 해주세요.');
  },
);

3초 뒤에 성공 호출하는 프로미스 함수를 적용하면 3초 뒤에 OK!, 가지러 가자!라는 문구가 출력된다.

여기서 then의 역할은 성공 실패 차례대로 첫번째는 성공 시에 실행되는 함수가 입력되는 곳이고 두번째는 실패 시에 실행되는 함수를 입력 해주면 된다.

then 대신에 사용될 수 있는 것으로는 catch와 finally가 있는데 위 예시의 then을 같은 형식으로 하여 먼저 catch는

pr.then(function (result) {	//성공 시에
  console.log(result + '!, 가지러 가자');
}).catch(function (err) {	//실패 시에
  console.log('다시 주문 해주세요.');
});

로 표현하여 명확하게 구분하여 가독성이 좋고 에러를 잡기에도 용이하여 사용이 권장된다.
여기에 finally까지 사용하면

pr.then(function (result) {	//성공 시에
  console.log(result + '!, 가지러 가자');
}).catch(function (err) {	//실패 시에
    console.log('다시 주문 해주세요.');
}).finally(function () {	//항시 실행
    console.log('=== 주문 끝 ===');
});

형태가 되는데 finally의 역할은 성공이든 실패든 이행 시에 꼭 실행되어야 하는 함수를 실행 시키는 역할이다.

해당 프로미스 함수 관련해서는 아직 나에게는 복잡한 개념이라 복습을 하며 어떠한 곳에 어떻게 적용 시킬지 고민을 많이 해봐야 하는 사항인 것 같다.

async / await

await은 async 함수 안에서만 동작하는 키워드이다.

만약, 함수 바깥에서 사용하면 SyntaxError가 발생한다.

Promise 함수를 기다리기 위해 await문은 Promise가 fulfill 되거나 reject 될 때까지 async함수의 실행을 일시 정지하고, Promise가 fulfill 되면 async함수를 일시 정지한 부분부터 실행합니다. 이때 await문의 반환 값은 Promise에서 fulfill 된 값이 됩니다. 만약, reject가 되면, await 문은 reject 된 값을 throw 한다.

function resolveAfter2Seconds(x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}

async function f1() {
  var x = await resolveAfter2Seconds(10);
  console.log(x); // 10
}

f1();

위의 예시의 f1 함수 안에 변수 x가 await이 사용되었다.

해당 함수가 실행되면서 변수 x가 있는 줄에서 실행이 잠시 중단되었다가 Promise가 이행(resolved) 될 때까지 기다렸다가 실행이 된다. 이때 변수 x에 값이 할당되게 되어 2초 뒤에 콘솔에 10이 찍히게 된다.

즉 await의 기능은 프라미스가 처리되길 기다리는 동안엔 엔진이 다른 일(다른 스크립트를 실행, 이벤트 처리 등)을 할 수 있기 때문에 CPU 리소스가 낭비되지 않는다.

await는 promise.then보다 좀 더 세련되게 프라미스의 result 값을 얻을 수 있도록 해주는 문법이다다. promise.then보다 가독성 좋고 쓰기도 쉽다.

Generator

Generator는 함수의 실행을 중간에 멈췄따가 재개 할 수 있는 기능이다.

function* fn() {
  console.log('1');
  yield 1;
  console.log('2');
  yield 2;
  console.log('3');
  console.log('4');
  yield 3;
  return 'finish';
}

const a = fn();

위와 같은 형태로 function 옆에 *을 붙여 제너레이터 함수를 선언하고 안에 yield라는 일종의 브레이크를 갖게 된다.

처음 실행 시에는 아무 것도 뜨지 않지만 console에 a.next();를 입력하게 되면 다음 브레이크(yield *;)까지 실행하는 구조이다. 해당 예시에서는 마지막 브레이크를 지나면 "finish"를 반환하고 한 번 더 next를 실행하면 undefined 값을 갖게 된다.

제너레이터의 특성으로는
iterable

  • Symbol.iterator 메서드가 있다.
  • Symbol.iterator는 iterator를 반환해야 한다.

iterator

  • next 메소드를 가진다.
  • next 메소드는 value와 done 속성을 가진 객체를 반환한다.
  • 작업이 끝나면 done은 true가 된다.

============복습 및 수정 필요==========

출처

내용 : https://www.youtube.com/watch?v=4_WLS9Lj6n4
내용 : https://juicyjerry.tistory.com/153

profile
https://github.com/WonseoYang

0개의 댓글