P4Ch5.클래스- Prototype과 Class

Prototype

prototype: 생성자 함수로부터 반환된 결과(인스턴스)에서 쓸 수 있는 속성 혹은 메소드를 등록하는 객체

fruits.includes, fruits.length 또한 프로토타입으로 등록된 속성,메소드이다.

1
2
3
4
5
6
7
//const fruits = ['Apple', 'Banana', 'Cherry']
const fruits = new Array("Apple", "Banana", "Cherry");
Array.prototype.heropy = function () {
  console.log(this);
};

fruits.heropy(); // ['Apple', 'Banana', 'Cherry']

Array라는 객체에 새로 heropy라는 프로토타입을 등록했다.

등록된 heropy를 호출하는 것으로 console.log(this)를 실행할 수 있다.

사용

1
2
3
4
5
6
7
8
9
10
11
12
const heropy = {
	firstName: 'Heropy',
	lastName: 'Park',
	getFullName: function () {
		return `${this.firstName} ${this.lastName}`
	}
const neo = {
	firstName: 'Neo'
	lastName: 'Anderson',
}

console.log(heropy.getFullName.call(neo)) // Neo Anderson

객체의 firstName과 lastName을 출력하는 예시이다. neo와 heropy에서 모두 getFullName 함수를 사용하는 방법으로는 neo에서 heropy에 있는 getFullName 함수를 빌려 사용하는 방법이 있다.

하지만 이는 getFullName을 사용하는 객체가 많아질 때마다 call 함수를 사용해야 한다는 점과, 객체의 사용이 직관적이지 못하다는 단점이 있다.

1
2
3
4
5
6
7
8
9
10
11
function User(first, last) {
  this.firstName = first;
  this.lastName = last;
}
User.prototype.getFullName = function () {
  return `${this.firstName} ${this.lastName}`;
};
const heropy = new User("Heropy", "Park");
const neo = new User("Neo", "Anderson");

console.log(heropy.getFullName()); //Heropy Park

이는 getFullName을 프로퍼티로 만드는 것으로 해결할 수 있다.

ES6 Class 기본 문법

위의 코드를 Prototype대신 class를 사용해 작성할 수 있다. class를 사용함으로써 문법적으로 더 직관적이고 명확한 코드를 작성할 수 있으며 생성자와 메소드, 상속을 더 쉽게 구현할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class User {
  constructor(first, last) {
    this.firstName = first;
    this.lastNAme = last;
  }
  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

const heropy = new User("Heropy", "Park");
const neo = new User("Neo", "Anderson");

console.log(heropy.getFullName()); //Heropy Park

class 키워드를 사용해 클래스를 정의하고 생성자 함수와 getFullName 메소드를 작성했다.

Prototype을 사용해 메소드를 수동으로 프로토타입에 추가한 것과 달리 class를 사용한 방식은 getFullName을 자동으로 프로토타입에 추가한다.

Prototype을 사용한 방식과 class를 사용한 방식 모두 동일한 기능을 수행한다.


정적 메소드

  • 프로토타입 메소드
    • 메소드 이름과 함수 정의 사이에 프로토타입 키워드 사용
      • Array.prototype.indefOf
  • 정적 메소드
    • 프로토타입 사용하지 않고 바로 클래스 혹은 함수에서 직접 호출됨.
      • Array.isArray()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class User {
  constructor(first, last) {
    this.firstNAme = first;
    this.lastNAme = last;
  }
  getFullName() {
    //프로토타입 메소드
    return `${this.firstName} ${this.lastName}`;
  }

  static isUser() {
    //정적 메소드
    if (user.firstNAme && user.lastName) {
      return true;
    }
  }
}

const heropy = new User("Heropy", "Park");

console.log(heropy.getFullName); //Heropy Park
console.log(User.getFullName); //Error!

console.log(User.isUser()); //true
console.log(heropy.isUser); //Error!

getFullName: 프로토타입 메소드는 heropy와 같은 instance에서 사용하는 것으로, class에서 호출할 수는 없다. 따라서 User 클래스에서 호출했을시 Error가 발생한다.

isUser: 정적메소드는 class에서 직접 호출이 가능하다. 반면에 instance에서는 사용 불가능하다. 따라서 인스턴스 heropy에서 호출했을시 Error가 발생한다.