javascript

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

Bittersweet- 2021. 12. 27. 16:06
728x90

생성자 함수란?

생성자 함수는 여러 프로그래밍 언어에서는 '클래스'와 동의어이다.

어떤 경우 사람들은 참조타임, 클래스, 데이터 타입, 아니면 간단하게 생성자라고 부른다.

 

메서드란?

메서드는 자바스크립트에서 객체를 만들기 위한 템플릿으로

생성자 함수 안에서 속성에 함수를 할당하면서 정의되며 생성자 함수와 함께 class를 사용한다.

hi 속성은 할당된 함수이다. Person 객체가 호출될때 this 키워드는 새로 생성된 Person 객체에 응답할 것이다.

** 메서드 사이엔 쉽표가 없음!!

class Person(name) {
  this.name = name;
  this.hi = function() { console.log(`Hi, My name is ${this.name}`) }
}

const kim = new Person('kim');
kim.hi(); // Hi, My name is kim

// Person 인스턴스가 생성될 때마다 이 객체는 Person.prototype에 선언된 어떤 속성이든, 메소드든 상속받게됨.
Person.prototype = {
  constructor: Person,
  Hi() {
    console.log('hi my name is'+ this.name);
    }
  }

 

 

1. class 생성자는 new와 함께 호출하지 않으면 에러가 발생한다.

class로 만든 함수엔 특수내부 프로퍼티인 [[FunctionKind]]: 'classConstructor'가 붙는다. 그래서 class를 사용하면 해당 프로퍼티를 확인하는 과정이 있기 때문에 new를 꼭 붙여야만 한다.

class User {
  constructor() {}
}

alert(typeof User); // function
User(); // TypeError: Class constructor User cannot be invoked without 'new'

2. 클래스의 메서드는 열거할 수 없다. (non-enumerable) 클래스의 prototype 프로퍼티에 추가된 메서드 전체의 enumerable 플래그는 false이기 때문이다.

즉, for...in으로 객체를 순회할 때, 메서드가 대상에서 제외된다.

 

3. 클래스는 항상 엄격모드로 실행된다.(use strict) 클래스 생성자 안 코드 전체에는 자동으로 엄격모드가 적용된다.

 

 

클래스란?

함수가 특정 기능을 하는 구문(알고리즘, 로직)을 묶을 때 사용하는 문법이라면, 클래스는 이렇게 만들어진 수많은 변수와 함수 중 연관 있는 변수와 함수만을 선별해 포장하는 기술이라고 할 수 있다.

다시 말해서, 연관있는 변수와 함수를 하나로 묶을 때 사용하는 문법이다.

 

클래스로 포장하는 이유는 객체 단위로 코드를 그룹화 할 수 있으며 코드를 재사용하기 위해서이다.

클래스는 객체 지향 프로그래밍에서 특정 객체를 생성하기 위해 변수와 메소드를 정의하는 일종의 틀로, 객체를 정의하기 위한 상태(멤버 변수)와 메서드(함수)로 구성된다.

class 선언만 해준다면 class 객체를 바로 만들 수 있다.

class Person {
}

let kim = new Person();

console.log(kim); // person{}

// 1. 리터럴 방식의 클래스
var 인스턴스 = {
  프로퍼티1 : 초기값,
  프로퍼티2: 초기값,
  메서드1: function() {
  //...
  },
  메서드2: function() {
  //...
  },
}

// 2. 함수 방식의 클래스
function 클래스 이름() {
  this.프로퍼티1 = 초기값;
  this.프로퍼티2 = 초기값;
  
  this.메서드1 = function() {
  //...
  }
  this.메서드2 = function() {
  //...
  }
}

var 인스턴스 = new 클래스 이름();

// 3. 프로토타입(prototype) 방식의 클래스
function 클래스 이름() {
  this.프로퍼티1 = 초기값;
  this.프로퍼티2 = 초기값;
}

클래스이름.prototype.메서드1 = function() {
//...
}
클래스이름.prototype.메서드2 = function() {
//...
}

- class 초기값 설정

Constructor를 이용하면 class 객체의 초기 값을 설정해줄 수 있다.

class 내부에는 한개의 Constructor만 존재할 수 있으며, 2번 사용 시 syntax error가 발생할 수 있다.

class person {
  constructor(name, age, city) {
    console.log('constructor');
    this.name = name;
    this.age = age;
    this.city = city;
  }
}

let kim = new Person('kim', '24', 'seoul');

console.log(kim); // constructor Person { name: 'kim', age: '24', city: 'seoul' }

- class 메서드 사용

class에서 설정한 초기값을 접근해 특정 기능을 하는 메서드를 만드는 것도 가능하다.

class안에 function 형식으로 만들어준 뒤 해당 메서드를 호출하기만 하면 된다.

class Person {
  constructor (name, age, city) {
    this.name = name;
    this.age = age;
    this.city = city;
  }
  //메서드 생성
  nextYearAge() {
    return Number(this.age) +1;
  }
 }
 
 let kim = new Person('kim', '24', 'seoul');
 
 console.log(kim.nextYearAge()); // 25

class는 javascript 상 객체의 형태이므로 생성된 class 객체에 class 밖에서 새로운 메서드를 넣는 것도 가능하다.

class Person {
  constructor(name, age, city) {
    this.name = name;
    this.age = age;
    this.city = city;
  }
  // 메서드 생성
  nextYearAge() {
    return Number(this.age) +1;
  }
}

let kim = new Person('kim', '24', 'seoul');

kim.eat = function() {
  return 'apple'
}

console.log(kim.nextYearAge()); // 25
console.log(kim.eat()); // apple

class 밖에서 추가한 eat이라는 메서드도 정확히 작동한다.

하지만, 이렇게 밖에서 추가한 class는 추후 새로운 new Person class 로 새로운 객체를 만들었을 때는 호출하여 사용할 수 없다.

class Person {
  constructor(name, age, city) {
    this.name = name;
    this.age = age;
    this.city = city;
  }
  //메서드 생성
  nextYearAge() {
    return Number(this.age) +1;
  }
}

let kim = new Person('kim', '24', 'seoul');

kim.eat = function() {
  return 'apple'
}

console.log(kim.nextYearAge()); // 25
console.log(kim.eat()); // apple

let part = new Person('park', '31', 'busan');

console.log(park.nextYearAge()); // 32
console.log(part.eat()); // TypeError: park.eat is not a function

- 상속(extends)

css에서 하나의 속성이 하위 속성에도 같이 적용되는 것처럼 class에서도 상속을 이용하면 기존의 class 값을 모두 접근하여 사용할 수 있다. 상속은 extends를 써서 이용한다.

class Person {
  constructor(name, age, city) {
    this.name = name;
    this.age = age;
    this.city = city;
  }
  // 메서드 생성
  nextYearAge() {
    return Number(this.age) +1;
  }
}

class introducePerson extends Person {
  introduce() {
    return `저는 ${this.city}에 사는 ${this.name} 입니다.`
  }
}

let kim = new introducePerson('kim','24','seoul');
console.log(kim.introduce()) // 저는 seoul에 사는 kim 입니다.

- super 사용

위의 예제에서 introducePerson 하위 클래스에서 기존 class 값을 가져다 쓰는 건 좋았지만 추가적으로 introducePerson이라는 하위 클래스에서만 사용하고 싶은 값이 있을 수도 있다.

이 때 super 키워드를 사용하며, 이는 객체의 부모가 가지고 있는 메서드를 호출할 수 있다.

자식 쪽의 추가적으로 사용할 초기값이 필요할 경우, constructor에 super로 부모 초기값을 세팅한 뒤 자식 class에서만 사용할 초기값을 따로 지정하는 것도 가능하며 super의 기능을 이용해서 자식 class에서 부모 메서드를 호출할 수도 있따.

class Person {
  constructor(name, age, city) {
    this.name = name;
    this.age = age;
    this.city = city;
  }
  // 메서드 생성
  nextYearAge() {
    return Number(this.age) +1;
  }
}

class introducePerson extends Person {
  constructor(name, age, city, futureHope) {
    super(name, age, city);
    this.futureHope = futureHope;
  }
  introduce() {
    return `저는 ${this.city} 에 사는 ${this.name} 입니다.
        내년엔 ${super.nextYearAge()}살이며,
        장래희망은 ${this.futureHope} 입니다.`
    }
  }
  
  let kim = new introductPerson('kim', '24', 'seoul' ,'개발자');
  console.log(kim.introduce()); // 저는 seoul에 사는 kim입니다. 내년엔 25살이며, 장래희망은 개발자입니다.