자바스크립트는 프로토타입
기반 객체지향 언어로 클래스가 필요 없는 객체지향 프로그래밍 언어다.
근데 갑자기 웬 클래스?
클래스가 없었던 ES5
에서는 생성자 함수
를 이용해 객체(인스턴스)를 생성하였다.
function Person(name) {
this.name = name;
this.sayHello = function () {
return `Hello, my name is ${this.name}!`;
};
}
생성자 함수로 사용하기 위해 작성한 Person을 new
와 함께 호출하면 객체(인스턴스)를 생성할 수 있다.
const chococheem = new Person('chococheem');
const raspberry = new Person('raspberry');
Person 생성자 함수를 통해 초코침이라는 사람(인스턴스)과 라즈베리라는 사람(인스턴스)을 만들었다.
이처럼 생성자 함수는 동일한 프로퍼티와 메서드를 갖는 객체를 여러 개 생성할 때 유용하게 쓸 수 있다. 하지만 위와 같이 작성한 생성자 함수는 객체지향 원칙 중 상속
을 구현할 수 없다. 그 이유는 생성자 함수에 의해 생성되는 모든 인스턴스가 메서드를 중복 생성하고 중복 소유하기 때문이다.
다음처럼 초코침
과 라즈베리
가 가지고 있는 메서드 sayHello를 비교해보자.
초코침의 sayHello
와 라즈베리의 sayHello
는 서로 다름을 알 수 있는데, 이는 각 인스턴스가 생성되면서 같은 역할을 하는 메서드일지라도 중복 생성하여 소유하고 있음을 의미한다.
이렇게 동일한 생성자 함수에 의해 생성된 모든 인스턴스가 동일한 메서드를 중복 소유하는 것은 메모리 사용 측면에서 낭비가 심할 뿐만 아니라, 상속을 구현할 수 없기 때문에 모든 인스턴스가 동일한 내용을 갖는 메서드는 단 하나만 생성하여 모든 인스턴스가 공유하며 사용하는 것이 바람직하다.
이러한 문제점 해결을 위해 자바스크립트는 프로토타입을 기반으로 상속을 구현한다. 동일한 내용의 메서드를 공유해서 사용할 수 있도록 메서드를 정의할 때 모든 인스턴스의 원형인 prototype
에 메서드를 추가해 주면 된다. 이때, Person이라는 생성자 함수 prototype에 메서드를 추가해야하므로 this 대신 생성자 함수 이름을 써 주어야 한다. 생성자 함수 내부의 this는 미래에 생성할 인스턴스를 가리키기 때문이다.
function Person(name) {
this.name = name;
Person.prototype.sayHello = function () {
return `Hello, my name is ${this.name}!`;
};
}
메서드를 생성자 함수의 prototype에 등록한 다음, 인스턴스를 만들어 메서드끼리 비교해보면 동일한 메서드를 공유하고 있음을 확인할 수 있다.
이는 프로토타입인 Person.prototype으로부터 sayHello라는 메서드를 상속받았음을 의미한다. 이로써 상속을 구현할 수 있게 되었다.
이처럼 자바스크립트는 프로토타입
이라는 개념으로 상속을 구현했다. 하지만 기존 객체지향 프로그래밍은 클래스 기반으로 구성돼 있어 클래스 기반에 익숙한 프로그래머들의 편의를 위해 프로토타입 기반 패턴을 클래스 기반 패턴처럼 사용할 수 있도록 ES6에서 클래스
가 도입되었다.
즉, 프로토타입 기반 모델을 폐지한 것이 아니라, 클래스처럼 쓸 수 있도록 하기 위한 것이기 때문에 자바스크립트의 클래스
는 문법적 설탕이라고 볼 수도 있다.
생성자 함수를 만들고 커서를 올리면 클래스로 바꿔 쓸 수 있다는 팁이 나온다.
클래스가 도입되었기 때문에 생성자 함수 대신 클래스를 사용하여 인스턴스를 생성할 수 있다. 위 Person 생성자 함수를 클래스 문법으로 작성하면 다음과 같다.
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
return `Hello, my name is ${this.name}!`;
}
}
생성자 함수와 달리, 클래스에서 메서드는 자동으로 prototype
의 메서드가 된다. 즉, 인스턴스끼리 같은 메서드를 공유한다.
클래스는 생성자 함수와 매우 유사하게 동작하지만, 클래스가 생성자 함수보다 엄격하며 더 많은 기능을 제공한다.
이걸 알고나니 자바스크립트로부터 좀 더 편의를 제공 받은 느낌이 든다 ㅋㅋ