클래스

1Hoit·2023년 1월 14일
0

자바스크립트

목록 보기
11/25

클래스

  • Class는 객체를 생성하기 위한 템플릿으로 클래스는 데이터와 이를 조작하는 코드를 하나로 추상화한다.
  • 클래스는 객체를 만들기위한 생성자 함수를 포함하며 new 키워드가 실행되면 생성자 함수가 실행 되며 변수에 클래스의 설계를 가진 인스턴스가 할당된다. (new연산자 없이 호출 할 수 없다)
  • 클래스는 속성과 메서드 정의, 인스턴스에선 이를 만들어 사용
  • 생성자 함수와 같이 클래스도 프로토타입 기반 객체 생성 메커니즘으로 볼 수 있다.

클래스 특징

클래스는 함수다. 또한 클래스도 일급객체다

  • 무명의 리터럴로 생성할 수 있다. 런타임 생성 가능
  • 변수나 자료구조(객체, 배열 등)에 저장 가능
  • 함수의 매개변수에 전달 가능
  • 함수의 반환값으로 사용 가능

클래스 작성 방식

  1. ES5 클래스 작성 문법 - 생성자 함수 사용
function Player(name){
	this.name = name;

   this.notice = function(name){
       alert(this.name);
   }
}
  1. ES6 클래스 작성 문법 - class 키워드 사용
class Player{
	constructor(name){
    	this.name = name;

    }
    notice(){
		alert(this.name);
    }
}
  1. 인스턴스 생성 (둘다 동일)
let pro = new Player('Caps')

클래스 구성

클래스 몸체에는 0개 이상의 메서드만 정의할 수 있다.
메서드로는 constructor(생성자), 프로토타입 메서드, 정적메서드 3가지가 있다.

그렇다면 생성자 함수와 클래스의 정의 방식 차이는?

정의 방식은 형태적인 면에서는 유사하다.

클래스 몸체의 메서드 (위의 클래스 구성 참고)

  1. constructor 메서드 :
  • 인스턴스를 생성하고 초기화하기 위한 메서드로 이름을 변경할 수 없다.
  • 인스턴스 프로퍼티는 constructor 내부에서 정의한다.
  • 생성자 함수와 마찬가지로 constructor 내부에서 this는 클래스가 생성한 인스턴스를 가리킨다.
  • 특징으로는 중복 불가능, 생략가능(암묵적으로 빈 constructor 생성), 초기화된 인스턴스 생성시 생략 불가능

이렇게 보면 constructor 가 헷갈린다.

  • 클래스의 constructor 메서드와 프로토타입 constructor 프로퍼티는 이름은 같지만 직접적인 관련이 없다.
  • 프로토타입 constructor 프로퍼티 = 모든 프로토타입이 가진 프로퍼티이며 생성자 함수를 가리킨다.
  1. 프로토타입 메서드
  • 클래스에서는 생성사 함수에 의한 객체 생성 방식과 달리prototype 프로퍼티에 메서드를 추가하지 않아도 기본적으로 프로토타입 메서드가 된다.
  • 생성자 함수와 마찬가지로 클래스가 생성한 인스턴스는 프로토타입 체인의 일원이 된다.
  1. 정적메서드
  • 인스턴스를 생성하지 않아도 호출할 수 있는 메서드
  • 클래스에서는 메서드에 static 키워드를 붙이면 정적메서드가 된다.
  • 정적 메서드는 클래스로 호출한다. 인스턴스가 아니다!
  • 정적 메서드는 인스턴스 프로퍼티를 참조할 수 없다!

    만약 위 그림에서 정적메서드를 호출하려면?

    1. 생성자 함수의 경우
      		Person.sayHello(); //Hello
    2. 클래스의 경우 (Person 클래스로 호출)
      		Person.sayHello(); //Hello
      만약 인스턴스로 호출한다면 타입 에러 발생

클래스에서 정의한 메서드의 특징

  1. function 키워드를 생략한 메서드 축약 표현을 사용 해야한다.
  2. 암묵적으로 strict mode로 실행
  3. for..in 문이나 Object.keys 메서드로 열거할 수 없음

생성자 함수 vs 클래스

  • 클래스와 생성자 함수 모두 프로토타입 기반의 인스턴스를 생성하지만 정확히 동일하게 동작하지 않는다.
  • 클래스는 생성자 함수보다 엄격하며 생성자함수에서 제공하지 않는 기능도 제공한다.
  1. 클래스는 new연산자 없이 호출하면 에러 / 생성자 함수는 일반함수로 호출된다.
  2. 클래스는 상속을 지원하는 extends와 super 키워드 제공
  3. 클래스는 호이스팅이 발생하지 않는 것처럼 동작 / 함수 선언문으로 정의된 생성자 함수는 함수호이스팅이, 함수표현식으로 정의했다면 변수호이스팅 발생
  4. 클래스 내의 모든 코드는 암묵적으로 strict mode 가 지정되어 실행된다.
  5. 클래스의 constructor, 프로토타입 메서드, 정적 메서드는 모두 프로퍼티 어트리뷰트 [[Enumerable]]값이 false다. 즉 열겨할 수 없다.

상속에 의한 클래스 확장

아래의 그림을 통해 상속에 대한 개념을 더욱 쉽게 알아보자

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

//상속을 통해 Animal 클래스를 확장한 Bird 클래스
class Bird extends Animal{
	fly(){return "Fly";}	
}

const bird = new Bird(1, 5);
console.log(bird)	//Bird {age:1, weight:5}
console.log(bird.eat()) // Eat
console.log(bird.fly()) // Fly

extends 키워드

  • 상속을 통해 클래스 확장시 사용되는 키워드
  • extends 키워드 앞에는 반드시 클래스가 와야한다.

super 키워드

  • super 호출시 부모 클래스의 constructor를 호출한다. ex) super();
  • super 참조시 수퍼 클래스의 메서드를 호출 할 수 있다. ex) super.sayHi();
  • 주의 사항
    1) 서브 클래스에서 constructor를 생략하지 않으면 서브 클래스의 constructor에서는 반드시 super를 호출 해야한다.
    2) 서브 클래스의 constructor에서 super를 호출하기 전에는 this를 참조할 수 없다. 즉 this보다 앞에서 호출 되어야 한다.
    3) super 는 반드시 서브클래스의 constructor 에서만 호출 해야한다.

class Polygon {
  constructor(height, width) {
    this.name = 'Polygon';
    this.height = height;
    this.width = width;
  }
  sayName() {
    console.log('Hi, I am a ', this.name + '.');
  }
}

class Square extends Polygon {
  constructor(length) {
    this.height; // 참조오류가 발생합니다. super가 먼저 호출되어야 합니다.

    // 여기서, 부모클래스의 생성자함수를 호출하여 높이값을 넘겨줍니다.
    // Polygon의 길이와 높이를 넘겨줍니다.
    super(length, length);

    // 참고: 파생 클래스에서 super() 함수가 먼저 호출되어야
    // 'this' 키워드를 사용할 수 있습니다. 그렇지 않을 경우 참조오류가 발생합니다.
    this.name = 'Square';
  }

  get area() {
    return this.height * this.width;
  }

  set area(value) {
    this.area = value;
  }
}

출처 및 참고 : MDN


마무리..

아직 부족한 내용들이 많다. 조금 더 보충해야 겠다.
그래도 대략적인 생성자 함수와 클래스, 인스턴스의 관계를 파악할 수 있게 되었다.

profile
프론트엔드 개발자를 꿈꾸는 원호잇!

0개의 댓글